home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / batchut / rap101.zip / COMMON.MAN < prev    next >
Text File  |  1992-05-08  |  105KB  |  3,076 lines

  1.  
  2.  
  3.                    A Common Subroutine Library
  4.  
  5.                        for RAP Programmers
  6.  
  7.  
  8.  
  9.                by Kirk H. Parker and Gary F. Simons
  10.                                 
  11.                                 
  12.  
  13.  
  14.                                 
  15.  
  16.  
  17.                                 
  18.                                 
  19.  
  20.  
  21.                                 
  22. Occasional Publications in Academic Computing
  23.  
  24. Number 10
  25.  
  26.  
  27.                                 
  28.                                 
  29.                                 
  30.                                 
  31.                                 
  32.                                 
  33.                                 
  34.                                 
  35.                                 
  36.                                 
  37.                                 
  38.                  Summer Institute of Linguistics
  39.                           Dallas, Texas
  40.  
  41. This book is sold with the software it describes.  That software,
  42. too, is the copyrighted property of the Summer Institute of
  43. Linguistics.  However, in the interest of sharing the fruit of
  44. our research with the larger academic community, the registered
  45. owner of the RAP software is granted the right to share copies of
  46. the distribution diskette with friends and associates, provided
  47. this is not done for commercial gain.  Such recipients of the
  48. software, if they decide to use it in their research, should in
  49. turn become registered owners by buying this book with its latest
  50. version of the software.
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.                                   
  67.                                 
  68.                                 
  69.       Copyright 1988 by the Summer Institute of Linguistics
  70.                        All rights reserved
  71.  
  72.  
  73.                              CONTENTS
  74.  
  75.  
  76. 1. Introduction                                  5
  77.  
  78.   1.1 Getting answers from the user              6
  79.  
  80.   1.2 File handling                              7
  81.  
  82.   1.3 Help system                                8
  83.  
  84.   1.4 String processing                          9
  85.  
  86.   1.5 Terminal control                           9
  87.  
  88.  
  89. 2. Using the common subroutine library          11
  90.  
  91.   2.1 Global variables used by the library      12
  92.  
  93.   2.2 Defined constants used by the library     13
  94.  
  95.   2.3 Internal error messages                   14
  96.  
  97.   2.4 Including the library in your programs    15
  98.  
  99.  
  100. 3. The help system                              17
  101.  
  102.   3.1 Creating a help file                      18
  103.  
  104.       3.1.1 Source file format markers          19
  105.       3.1.2 Producing the working help file     20
  106.  
  107.   3.2 Using the help file in your program       21
  108.  
  109.       3.2.1 Opening the help file               22
  110.       3.2.2 Using explain and #verbose          22
  111.       3.2.3 Using the $topic parameter          23
  112.       3.2.4 Help in menus                       24
  113.  
  114.  
  115. 4. An example program                           27
  116.  
  117.   4.1 File header and .include files            28
  118.  
  119.   4.2 Defined constants                         29
  120.  
  121.   4.3 Main subroutine                           29
  122.  
  123.   4.4 Testing the environment                   31
  124.  
  125.   4.5 Getting the parameters                    33
  126.  
  127.   4.6 Generating a customized PTP program       34
  128.  
  129.   4.7 Running the generated PTP program         38
  130.  
  131.  
  132. 5. Reference summary of the COMMON subroutine library  41
  133.  
  134.  
  135. References                                      97
  136.  
  137.  
  138. Index                                           99
  139.  
  140.  
  141. ----------------------------------------------------------------
  142.  
  143. Chapter 1
  144.  
  145.  
  146. INTRODUCTION
  147.  
  148.  
  149.       1.1 Getting answers from the user
  150.  
  151.       1.2 File handling
  152.  
  153.       1.3 Help system
  154.  
  155.       1.4 String processing
  156.  
  157.       1.5 Terminal control
  158.  
  159.  
  160.   The RAP  language (Strangfeld 1988) was designed especially for
  161. writing computer  programs that interact heavily with users.  RAP
  162. makes it  easy to display text on the terminal screen, and to get
  163. and test  responses typed  by users.   RAP's high-level features,
  164. such as  the menu-construct  and built-in pattern matching, allow
  165. complicated control structures to be programmed with a minimum of
  166. effort.
  167.  
  168.   The philosophy  behind RAP  is not,  however, to  provide every
  169. possible user-interface feature as a built-in function.  Instead,
  170. RAP seeks  to provide  the basic  building blocks from which such
  171. features can  be constructed.   To support this, RAP provides for
  172. extension in  two ways:   the  set of  program  commands  can  be
  173. extended by  adding  user-defined  procedures,  and  the  set  of
  174. program functions  can be extended by adding user-defined numeric
  175. functions and string functions.  These user-defined constructs we
  176. refer to collectively as subroutines, or simply routines.
  177.  
  178.   This volume describes one set of subroutines which extend RAP's
  179. capabilities in  the areas  of user  interaction, file  handling,
  180. context-sensitive help,  string processing, and terminal control.
  181. The subroutine  library is  called COMMON,  because it contains a
  182. set of  commonly needed  procedures and  functions.   We envision
  183. that this  COMMON library  will be  used by  virtually every  RAP
  184. application program.   The  library  is  contained  in  the  file
  185. COMMON.RAP.   To make  use of the subroutines, a programmer needs
  186. only to include the line
  187.  
  188.   .include common.rap
  189.  
  190. in the  main RAP  program file.   The simplicity of accessing the
  191. library makes  it possible  for even  novice programmers  to make
  192. full use of the subroutines.
  193.  
  194.   The following  sections give  a brief  overview of the library,
  195. listing  the   subroutines  according   to   general   functional
  196. categories.
  197.  
  198.  
  199. 1.1 Getting answers from the user
  200.  
  201.   The COMMON  library includes  routines to get and validate user
  202. inputs.   All of these routines allow the programmer to specify a
  203. prompt and  a default  response.   Programmers can specify limits
  204. such as string length, minimum and maximum numeric values, and so
  205. on.   The routines  in this  group, listed  below, also allow the
  206. programmer to  specify a  help topic  as a  parameter.  If a help
  207. topic is  provided, the  user can display the help information by
  208. entering ? or help in response to the prompt.
  209.  
  210.   *get_code     Get an  SIL standard  format marker  (slash code)
  211.                 from the user.
  212.  
  213.   *get_num      Get a number from the user.
  214.  
  215.   *get_str      Get a string from the user.
  216.  
  217.   *get_ans      Display a  query and  get  a  response  from  the
  218.                 user≡a  low-level  function  used  by  the  other
  219.                 functions in this group.
  220.  
  221.   *no           Ask the user a yes/no question, reporting true if
  222.                 the answer is no.
  223.  
  224.   *yes          Ask the user a yes/no question, reporting true if
  225.                 the answer is yes.
  226.  
  227.  
  228. 1.2 File handling
  229.  
  230.   The COMMON  library includes  subroutines which  get file names
  231. and then verify that they can be used safely for input or output.
  232. Other subroutines  support  safe  deletion  of  files,  automatic
  233. generation of  backup files, and control of mounted disk files or
  234. volumes.
  235.  
  236.   *delq         Interactively  delete   a  file  and  report  the
  237.                 result.   If the  file exists,  the user is asked
  238.                 whether or not to delete it.
  239.  
  240.   *get_append_file  Get a  file name  for  editing  or  updating.
  241.                 Create an empty file if none exists, but preserve
  242.                 the contents of an existing file.
  243.  
  244.   *get_fixed_output Ensure that a predefined name can be used for
  245.                 an output file.  Optionally get a substitute name
  246.                 from the user, if not.
  247.  
  248.   *get_input_file   Get a file name from the user and ensure that
  249.                 it is a valid, existing file.
  250.  
  251.   *get_output_file  Get a  file name  from the user for an output
  252.                 file.   If a  file with  the given  name  already
  253.                 exists, the  user is  asked  whether  or  not  to
  254.                 overwrite it.
  255.  
  256.   make_bak_file Perform an  automatic file  backup.  The existing
  257.                 .BAK file is deleted, the previous version of the
  258.                 file is renamed as a .BAK file, and the .TMP file
  259.                 is renamed to the original name.
  260.  
  261.   make_bak_to_bat   Perform an  automatic file  backup as  above,
  262.                 but do  so by  writing the necessary DOS commands
  263.                 to a  batch file.   This  is  required  when  the
  264.                 target machine  does not  have enough  memory for
  265.                 RAP to execute DOS-level commands as subtasks.
  266.  
  267.   *make_tmp_output  Generate and validate a temporary output file
  268.                 name.
  269.  
  270.   mount_file    Ensure that a particular data file is mounted.
  271.  
  272.   mount_program Ensure that a particular program file is mounted.
  273.  
  274.   mount_volume  Ensure that  a particular  disk volume is mounted
  275.                 in a particular drive.
  276.  
  277. Also included  are some lower-level subroutines used to build the
  278. above  file-handling  routines.    They  can  be  used  to  build
  279. specialized file-handling routines.
  280.  
  281.   *deletef      Delete a file and report the result.
  282.  
  283.   *ensure_dot   Ensure that a file extension begins with a dot.
  284.  
  285.   ensure_space  Test for disk space for output file.  If there is
  286.                 not enough  room, ask  the user  to  delete  some
  287.                 files.
  288.  
  289.   *get_filespec Get a  filespec from  the user and ensure that it
  290.                 is well-formed.
  291.  
  292.   *parse_filespec   Ensure that  a filespec  is well-formed,  and
  293.                 break it down to its four main components.
  294.  
  295.   *val_dir      Report if the subdirectory part of a path name is
  296.                 valid.
  297.  
  298.   *val_drive    Report if a drive name is valid.
  299.  
  300.   *val_ext      Report if a file extension is valid.
  301.  
  302.  
  303. 1.3 Help system
  304.  
  305.   The COMMON  library includes  routines to support on-line help.
  306. The help  information is stored as text in a file external to the
  307. application program.  Help specific to the current context in the
  308. program is displayed, either when the program explicitly commands
  309. it, or  when the  user asks  for help  by typing  ?  or  help  in
  310. response to one of the query routines of the library.
  311.  
  312.   explain       Display help information on a given topic.
  313.  
  314.   open_help     Open the program's help file.
  315.  
  316.  
  317. 1.4 String processing
  318.  
  319.   The COMMON  library extends  RAP's built-in  string  operations
  320. with a few higher-level routines.
  321.  
  322.   *to_lower     Convert all  upper-case letters  in a  string  to
  323.                 lower-case.
  324.  
  325.   *to_upper     Convert all  lower-case letters  in a  string  to
  326.                 upper-case.
  327.  
  328.   *trim         Remove leading  and trailing spaces and tabs from
  329.                 a string.
  330.  
  331.  
  332. 1.5 Terminal control
  333.  
  334.   The COMMON  library provides routines which give the programmer
  335. control over  the terminal in case something goes wrong.  For the
  336. screen this  involves the  display of  error and warning messages
  337. with built-in  pause to  ensure that the user sees them.  For the
  338. keyboard this  involves flushing  the type-ahead buffer to remove
  339. input that  is potentially  invalidated by  the occurrence  of  a
  340. problem.
  341.  
  342.   kbflush       Remove any keystrokes in the type-ahead buffer.
  343.  
  344.   message       Display a  message text  and pause  to ensure the
  345.                 user sees it.
  346.  
  347.   retry         Display an  error message  resulting from invalid
  348.                 user input,  and ask  the user  to  re-enter  the
  349.                 answer.
  350.  
  351.  
  352. ----------------------------------------------------------------
  353.  
  354. Chapter 2
  355.  
  356.  
  357. USING THE COMMON SUBROUTINE LIBRARY
  358.  
  359.  
  360.       2.1 Global variables used by the library
  361.  
  362.       2.2 Defined constants used by the library
  363.  
  364.       2.3 Internal error messages
  365.  
  366.       2.4 Including the library in your programs
  367.  
  368.  
  369.   There are  a number  of things  you must  know in  order to use
  370. COMMON.RAP correctly  in your  own program.  First, you must know
  371. what subroutines  are in  the library  and how  each is used.  An
  372. overview is  given in  chapter 1;  full details  are provided  in
  373. chapter 5.   If  you want to provide users with context-sensitive
  374. help, you  will need  to understand  how the subroutine library's
  375. help system  works; this  is explained in chapter 3.  The current
  376. chapter covers  topics  which  are  relevant  to  the  subroutine
  377. library in  general, namely,  the global  variables  and  defined
  378. constants used  in the library, the internal error mechanism, and
  379. how to  include the  COMMON.RAP file  in your program.  Chapter 4
  380. ties everything together with a complete sample program.
  381.  
  382.  
  383. 2.1 Global variables used by the library
  384.  
  385.   The subroutine  library creates  and uses  a number  of  global
  386. variables.   Some of  them are  primarily for internal use by the
  387. subroutines.   Others are  directly useful to the programmer.  In
  388. either case,  programmers must  avoid using these names for their
  389. own variables.  These global variables are:
  390.  
  391.   $drive        The  drive  part  of  the  most  recent  filespec
  392.                 entered by the user.
  393.  
  394.   $ext          The extension  part of  the most  recent filespec
  395.                 entered by the user.
  396.  
  397.   #filesize     The size  (in kilobytes)  of the  last input file
  398.                 entered by  user.    (Note  that  RAP's  built-in
  399.                 functions *filesize,  *freesp, and  *memfree work
  400.                 in units  of bytes,  rather than  kilobytes.  The
  401.                 programmer who  wants to  mix COMMON's high-level
  402.                 routines with  direct  calls  to  RAP's  built-in
  403.                 functions must be sure to compensate.)
  404.  
  405.   $name         The name part of the most recent filespec entered
  406.                 by the user.
  407.  
  408.   $skip         Used by  the subroutines  to adapt  to  different
  409.                 display sizes.  This  variable  contains  a  null
  410.                 string if  the program  is running on a Sharp PC-
  411.                 5000, and  a newline character on other machines.
  412.                 $skip allows  subroutines to  include blank lines
  413.                 where desired  on PC-compatibles, without wasting
  414.                 screen lines  on the Sharp.  Your own subroutines
  415.                 can make use of this variable.
  416.  
  417.   $subdir       The subdirectory part of the most recent filespec
  418.                 entered by the user.
  419.  
  420.   $valdr        Contains a  list of  valid disk drive designators
  421.                 for the  machine on which the program is running.
  422.                 See the  entry in  chapter 5  for the  subroutine
  423.                 *val_drive for more information on this variable.
  424.  
  425.   #verbose      Enables or disables the help function provided by
  426.                 the subroutine explain.
  427.  
  428.   In addition to these variables, COMMON uses a few which are for
  429. internal use only.  The names of these variables all end with two
  430. underscores.  Your programs should avoid using any names that end
  431. with two  underscores to  avoid  possible  conflicts  with  these
  432. names.
  433.  
  434.  
  435. 2.2 Defined constants used by the library
  436.  
  437.   COMMON.RAP includes  a number  of defined  constants.  Like the
  438. global variables,  some of  them may  be directly  useful to  the
  439. programmer and  all of  them are  reserved names  (that is,  they
  440. cannot be used by a programmer to define some other value).
  441.  
  442.   The .define's  are used  because they  make programs  easier to
  443. read, write, and understand.  For example, instead of writing
  444.  
  445.   if (*existf($some_file) == 4)
  446.      t:Sorry, you can't delete that file.
  447.  
  448. you can write
  449.  
  450.   if (*existf($some_file) == .READONLY)
  451.      t:Sorry, you can't delete that file.
  452.  
  453.   Not only  is the  latter clearer  to someone  else reading  the
  454. program, it  is also  easier for  the programmer  to write;  most
  455. people can remember .READONLY more readily than they can remember
  456. that 4 means a read-only file!
  457.  
  458.   The defined  symbols fall  into three  categories.   The  first
  459. consists of return values for the library subroutines themselves:
  460.  
  461.   .YES          1
  462.   .NO           0
  463.  
  464.   The second  group represents  return values  from the  built-in
  465. function *existf:
  466.  
  467.   .NOTFOUND     0
  468.   .READWRITE    2
  469.   .READONLY     4
  470.  
  471.   The third  group contains  general  system  values  and  useful
  472. abbreviations:
  473.  
  474.   .MININT       The smallest negative number allowed by RAP.
  475.  
  476.   .MAXINT       The largest positive number allowed by RAP.
  477.  
  478.   .FILECHARS    A list  of all characters which are valid in file
  479.                 names, namely, all upper- and lower-case letters,
  480.                 all digits,  and the following punctuation marks:
  481.                 !@#$%^&()'`{}~-_
  482.  
  483.   .MAXCODE      The maximum  length allowed for a standard format
  484.                 marker.
  485.  
  486.   .LOCALMATCH   Contains  the   string  "declare  $left,  $match,
  487.                 $right".   When executed  in a  RAP program, this
  488.                 code creates local copies of the pattern-matching
  489.                 variables.   This definition serves two purposes:
  490.                 the defined  name is shorter (and easier to type)
  491.                 than  its   replacement,  and   it  more  clearly
  492.                 documents the reason for the declared variables.
  493.  
  494.  
  495. 2.3 Internal error messages
  496.  
  497.   It is  possible to  call a  subroutine with invalid parameters.
  498. For example, the library subroutine *get_num, which gets a number
  499. from the  user, allows  the programmer  to specify limits for the
  500. minimum and  maximum values  the user  is allowed to enter.  What
  501. happens if  the programmer  accidentally sets  the maximum  limit
  502. less than  the minimum?  If the subroutine did nothing about this
  503. error, the user would be unable to enter a valid response.
  504.  
  505.   The  library   subroutines  attempt   to  detect  such  invalid
  506. parameters, because  invalid parameters represent serious logical
  507. errors in  the program,  and may  well cause  the program to give
  508. invalid results.  If such an error is detected, an internal error
  509. message similar to the following is displayed:
  510.  
  511.   
  512.   Internal error in *get_num:
  513.   
  514.      minimum greater than maximum
  515.   
  516.   The program will continue to run, but the results
  517.   may not be correct.  Copy this message for reporting
  518.   to the program's author.  You may quit immediately
  519.   by typing Ctrl-C.
  520.  
  521. This warns  the user that something has gone wrong in the program
  522. and supplies  debugging information  that can be passed on to the
  523. programmer.   Of course,  if you  are careful  about testing your
  524. programs before  releasing  them,  you  will  encounter  all  the
  525. internal error  messages yourself  and correct  the errors before
  526. releasing your  program.   If you  do this,  the end  user should
  527. never see such a message.
  528.  
  529.  
  530. 2.4 Including the library in your programs
  531.  
  532.   To use  the subroutines  in  the  library,  you  must  use  the
  533. .include command  to bring the file COMMON.RAP into your program.
  534. Except for  any loose  code you may have at the beginning of your
  535. program file,  .include COMMON.RAP  must be  the first command in
  536. the file.  This is necessary because COMMON.RAP begins with loose
  537. code which initializes key variables like #verbose and $skip.  If
  538. you fail to put .include COMMON.RAP in the right place, the loose
  539. code will  cause program  loading to  terminate with the message,
  540. "Unreachable statement(s) found after proc/function end."
  541.  
  542.   After .include  COMMON.RAP, we  recommend  that  you  put  your
  543. .define's, then  your .include's,  then your  main procedure, and
  544. finally all  other procedure  and  function  definitions.    This
  545. arrangement of  a RAP  program is  illustrated in  the  following
  546. example:
  547.  
  548. ; sample.rap        sample program showing how to
  549. ;                   include COMMON.RAP
  550.  
  551. ;----------------------------------------------------------
  552. ; We do not recommend that you use loose code in your
  553. ; programs, but if you do, ALL loose code must come here
  554. ; before including COMMON.RAP.
  555.  
  556. .include common.rap
  557.  
  558. ;----------------------------------------------------------
  559. ; Any .defines that you want to be available to your whole
  560. ; program should come next -- for example, a default record
  561. ; marker:
  562.  
  563. .define .DEFAULT_MARK last_name
  564.  
  565. ;----------------------------------------------------------
  566. ; Next comes any other include-files.  For example, you may
  567. ; have a file of RAP subroutines that generate Manuscripter
  568. ; commands:
  569.  
  570. .include ms_gen.rap
  571.  
  572. ;----------------------------------------------------------
  573. ; As a matter of style, the main procedure should be the
  574. ; first subroutine in your program.
  575.  
  576. proc main()
  577.  
  578. ; If you are supplying a help file with your program, you
  579. ; must open it by calling open_help before calling any
  580. ; other library subroutine
  581.  
  582. cls
  583. t:      SAMPLE.RAP
  584.  
  585. open_help("my_help.hlp")
  586. ...
  587.  
  588. end proc
  589.  
  590. ;----------------------------------------------------------
  591. ; After the main procedure come any other subroutines
  592. ; in your program file:
  593.  
  594. proc page_params()      ; get Manuscripter page parameters
  595. ...
  596.  
  597. end proc
  598.  
  599. ...
  600.  
  601.  
  602. ----------------------------------------------------------------
  603.  
  604. Chapter 3
  605.  
  606.  
  607. THE HELP SYSTEM
  608.  
  609.  
  610.       3.1 Creating a help file
  611.  
  612.           3.1.1 Source file format markers
  613.           3.1.2 Producing the working help file
  614.  
  615.       3.2 Using the help file in your program
  616.  
  617.           3.2.1 Opening the help file
  618.           3.2.2 Using explain and #verbose
  619.           3.2.3 Using the $topic parameter
  620.           3.2.4 Help in menus
  621.  
  622.  
  623.   It is  important for  your programs  to provide  on-line  help.
  624. Although a  printed manual  is a  key part  of a program package,
  625. users who  have questions  while running a program ideally should
  626. not have  to search  through the  manual.    The  COMMON  library
  627. provides an  extensive help  system that  allows you  to  provide
  628. context-sensitive help information for your users.
  629.  
  630.   The library  supports two  ways of displaying help information.
  631. The first is using the subroutine explain.  For example, in order
  632. to present  an introduction  to the  user, you  could  write  the
  633. following command into your program:
  634.  
  635.   explain("intro")
  636.  
  637.   The second means is provided by the interactive input routines:
  638. *get_ans,     *get_append_file,     *get_code,     *get_filespec,
  639. *get_fixed_output, *get_input_file,  *get_num,  *get_output_file,
  640. *get_str, *no,  and *yes.  These functions  all have  a parameter
  641. called $topic.   When you pass the name of a help topic to one of
  642. these routines,  the help  information is  displayed if  the user
  643. types ?  or help in response to the query.  This means that every
  644. time you  ask users  for input,  you can provide explanatory help
  645. for that specific input.
  646.  
  647.   The  help  system  uses  an  external  help  file  rather  than
  648. including the  help text  in the  program file.  An external file
  649. has two  benefits.   The first  is that  the help  file  and  the
  650. program can  be revised  independently of each other.  The second
  651. is that the help file does not take up any memory space while the
  652. program is  running.   There is  thus no  penalty  for  including
  653. extensive on-line help messages.
  654.  
  655.  
  656. 3.1 Creating a help file
  657.  
  658.   Creating a help file involves two steps.  The first is to write
  659. a text  file containing  the help  text for every topic.  This is
  660. called the  source file.  The second is to process that file with
  661. the helpgen  program.   (This program  is  included  on  the  RAP
  662. release disk  as HELPGEN.EXE.)  Helpgen reads the source file and
  663. generates an  index for  it which enables explain to quickly find
  664. the help text associated with any given help topic.  Helpgen then
  665. writes a  new copy  of the help texts with the index added at the
  666. beginning.  This indexed file is called the help file.
  667.  
  668.   You should  not attempt  to  edit  the  help  file  created  by
  669. helpgen.   The index  uses a  byte count to indicate the starting
  670. location of each topic entry.  If your attempted revision changes
  671. the length  of the file by even one byte, all or part of the help
  672. file will  be rendered invalid.  An incorrectly indexed help file
  673. can even cause RAP to abort the current program and return to the
  674. command level!   The  only safe  way to  change a help file is to
  675. edit the source file and process it again with helpgen.
  676.  
  677. 3.1.1 Source file format markers
  678.  
  679.   The source  file is  a plain  ASCII text  file which  uses  SIL
  680. standard format markers to organize it.  SIL standard format is a
  681. convention which  prescribes that  different types of information
  682. in text files should be marked by unique codes beginning with the
  683. backslash character.   (For  this reason, standard format markers
  684. are also  called slash  codes.)   The following  standard  format
  685. markers are recognized in the help source file:
  686.  
  687.   \id     File identification.  The first line of the file, if so
  688.           marked, contains identification information inserted by
  689.           the author  of the  source file.   It  is optional, but
  690.           strongly recommended!
  691.  
  692.   \topic  Help topic definition.  This marker must be followed by
  693.           the name of a help topic on the same line.  Topic names
  694.           follow the  same rules  as RAP  names: they  must begin
  695.           with a  letter,  contain  only  letters,  numbers,  and
  696.           underscores, and be no longer than 19 characters. Upper
  697.           and lower  case are considered equal: INTRO, Intro, and
  698.           intro all refer to the same help topic.
  699.  
  700.   \cls    Performs a  RAP cls  (clear  screen  and  home  cursor)
  701.           command  when   encountered  in   a  help   text  being
  702.           displayed.  This marker must be alone on a line.
  703.  
  704.   \foot   Performs a  RAP foot  (pause at foot of screen) command
  705.           when encountered  in a help text being displayed.  This
  706.           marker must be alone on a line.
  707.  
  708.   \__     Reserved for  use by helpgen (backslash followed by two
  709.           underscores).
  710.  
  711.   In order to be recognized, these markers must begin at the left
  712. margin.   Any lines beginning with anything else (including other
  713. standard format  markers) are part of the help text for the topic
  714. defined by the most recent \topic.
  715.  
  716.   The \foot  and \cls  markers are never required, provided RAP's
  717. automatic screen  paging is  enabled.  If you have turned off the
  718. paging by the RAP statement #paged = 0, you will probably need to
  719. use \foot  in your  help texts  to prevent  help information from
  720. scrolling off  the screen  before it can be read.  Even if paging
  721. is on,  you may want to use these markers to group your help text
  722. into paragraphs  or "screenfuls."   Another  use for  \cls is  to
  723. clear the  screen before  beginning the help text.  In this case,
  724. the \cls should be on the first line after the \topic.
  725.  
  726.   You may  use any  printing characters  in the help source file,
  727. including extended  ASCII characters.  You should not include any
  728. control characters  (not even  TABs).   Blank lines in the source
  729. text are  not modified  in any way, so you may use them to format
  730. your help text into paragraphs.
  731.  
  732.   The following  is a  sample help source file which defines help
  733. texts for three topics, namely intro, help_source, and help_file:
  734.  
  735.   
  736.   \id sample.txt  Sample help file source   14-DEC-87  khp
  737.   \topic intro
  738.   Welcome to the sample program.  This is only a sample.
  739.   If it had been a real program, some useful data would
  740.   have been produced or processed.
  741.   \topic help_source
  742.   A help source file is a standard format file containing
  743.   the help text.
  744.   \topic help_file
  745.   The actual help file contains an index to the help
  746.   topics, followed by the contents of the source file.
  747.   \foot
  748.   The help file is created from the source file by the
  749.   program HELPGEN.EXE.  This program generates an index to
  750.   the help topics, and then creates the help file which
  751.   contains the index followed by all of the help texts.
  752.   \foot
  753.   \cls
  754.   
  755.  
  756. Note that  if you use \cls on any line except the first line of a
  757. topic, you  should place  a \foot before it to prevent the screen
  758. from clearing before the user has read the help text.
  759.  
  760. 3.1.2 Producing the working help file
  761.  
  762.   After creating  the help  source file,  you process it with the
  763. program helpgen.  This creates the working help file that you use
  764. with your RAP program. Helpgen takes two command-line parameters,
  765. the name  of the  input source  file and  the name of the desired
  766. output help  file.   Helpgen prompts  you for  any parameters you
  767. don't enter  on the  command line.  Thus you may run helpgen with
  768. one of the following command lines:
  769.  
  770.   
  771.   helpgen
  772.   
  773.   helpgen input_file
  774.   
  775.   helpgen input_file output_file
  776.   
  777.  
  778. If you  don't specify  an output  file name,  it will  suggest  a
  779. default name  based on  the input  file name  with the  extension
  780. .HLP.   Regardless of  how the  file names  are obtained, helpgen
  781. prevents you  from entering  the same  name for  both  input  and
  782. output.
  783.  
  784.   As helpgen  runs,  it  may  display  error  messages  like  the
  785. following:
  786.  
  787.   Error in line number: \topic without argument
  788.   Error in line number: duplicate name (topic_name)
  789.   Error in line number: file too big (\topic topic_name)
  790.  
  791.   The first message means that you forgot to include a topic name
  792. after the  \topic marker,  or that  the name  is on the following
  793. line instead  of the  same line.  Edit the source file and add or
  794. move the name as required, and run helpgen again.
  795.  
  796.   The second  message means  that you have used the same name for
  797. more than  one \topic  entry.   If you  attempted to use the help
  798. file, *explain  would only be able to find the first entry.  Edit
  799. the help  source file  and change  one of  the names.   Then  run
  800. helpgen again.   You  may also need to edit your RAP source files
  801. and revise the topic names used there.
  802.  
  803.   The final  error message  indicates a more serious problem with
  804. your help  file.   Help files  have an absolute upper size limit.
  805. (The limit  may vary  with versions  of helpgen.   See the README
  806. file on  the release  disk for the exact limit of the version you
  807. have.)   The error message means that, after processing, the size
  808. limit has  been reached  before all  the text for the named topic
  809. was included.   You  must reduce  the overall  size of  the  help
  810. source file.
  811.  
  812.  
  813. 3.2 Using the help file in your program
  814.  
  815.   After you  have created  a help  file, you  can use  it in your
  816. program.   You need  to open  the  help  file,  use  the  explain
  817. procedure and  the $topic parameters, and optionally set or reset
  818. the global variable #verbose.
  819.  
  820. 3.2.1 Opening the help file
  821.  
  822.   The first step in using the help file is to call the subroutine
  823. open_help to  open the  file.   You should  do this early in your
  824. main procedure,  and must  do it  before any  calls to  any other
  825. library subroutines.  Here is a simple example:
  826.  
  827.   
  828.   ; helpdemo.rap   demonstrate use of open_help in a
  829.   ;                program to help user generate a
  830.   ;                help source file
  831.   
  832.   .include common.rap
  833.   
  834.   proc main
  835.   
  836.   open_help("helptest.hlp")
  837.   
  838.   ; now we can use explain:
  839.   
  840.   explain("intro")
  841.   
  842.   ; as well as calls to the library that include
  843.   ; $topic parameters:
  844.   
  845.   if (*yes("Do you want to produce a help source file","",+
  846.            "help_source"))
  847.      produce_source
  848.   end if
  849.   
  850.   end proc
  851.   
  852.  
  853.  
  854. 3.2.2 Using explain and #verbose
  855.  
  856.   The subroutine explain is used to display help information when
  857. the programmer wants to force an explanation, rather than waiting
  858. for the  user to  ask for  help when  answering a  query.  In the
  859. example  above,   explain("intro")   will   always   display   an
  860. introduction at the beginning of the program.
  861.  
  862.   The example  has one obvious problem, however.  As users become
  863. familiar with the program, they will probably get tired of seeing
  864. the introduction  every time  they run  it.   A good  help system
  865. should display  information only  when it  is needed  and wanted.
  866. One solution would be to write
  867.  
  868.   if (*yes("Do you want to read the introduction","",""))
  869.      explain("intro")
  870.   end if
  871.  
  872. But if  the program contains numerous calls to explain, every one
  873. will have  to be  enclosed within an if-construct.  To avoid this
  874. necessity, explain  checks  the  value  of  the  global  variable
  875. #verbose every  time it  is called.   If  #verbose has a value of
  876. zero, explain  returns immediately to the calling routine without
  877. displaying anything.   If  the value is non-zero, the explanation
  878. is given  as normal.  You can thus enable or disable explanations
  879. for the  entire program  by setting  the value  of #verbose.  For
  880. instance, a  program could be written like this in order to allow
  881. the user to control the display the explanations:
  882.  
  883.   
  884.   .include common.rap
  885.   
  886.   proc main
  887.   
  888.      open_help("helptest.hlp")
  889.      #verbose = *yes("Do you want instructions","","")
  890.      explain("intro")
  891.   ...
  892.      explain("helpgen")
  893.   ...
  894.   
  895.   end proc
  896.   
  897.  
  898. Not only does #verbose make it easier for the programmer to write
  899. the program, it also makes it more convenient for the experienced
  900. user who  can turn off all the explanations by answering a single
  901. question.
  902.  
  903. 3.2.3 Using the $topic parameter
  904.  
  905.   When one  of the  interactive input  subroutines is  used,  the
  906. programmer can  provide a  help topic.   The  help topic  will be
  907. displayed if  the user enters ? or help in response to the query.
  908. For instance,  in the  previous example we could rewrite the line
  909. which sets #verbose to include a help topic for *yes:
  910.  
  911.   #verbose = *yes("Do you want instructions","","verbose")
  912.  
  913. In this  case, the  help topic  verbose would  explain  something
  914. about the  instructions available  in the  program and  about the
  915. consequences of  answering yes  or no to the query.  Ideally, any
  916. time the  user is  asked for  input, the program should provide a
  917. help topic to give a brief explanation of the significance of the
  918. answer, of the range of allowable answers, and so forth.
  919.  
  920.   The explanations  provided for  help topics  passed  as  $topic
  921. parameters are not affected by the setting of #verbose.  #Verbose
  922. only affects  calls to explain that are part of your RAP program.
  923. This means  that users  can  turn  off  informative  or  tutorial
  924. explanations without  losing the  ability to  call for  help when
  925. needed.
  926.  
  927.   This effect  is achieved  by declaring a local copy of #verbose
  928. within the lowest-level subroutine which COMMON.RAP uses for user
  929. input.   The  essential  structure  of  this  subroutine,  called
  930. *get_ans, is sketched below:
  931.  
  932.   
  933.   string func *get_ans( . . , $topic, . .)
  934.   
  935.      declare #verbose  ; create a local version of #verbose
  936.   
  937.      #verbose = 1      ; explain is now enabled, but the
  938.                        ; previous setting will be restored
  939.                        ; when this function returns.
  940.      ...
  941.      if ($answer == "?" or $answer == "help")
  942.         explain($topic)
  943.      end if
  944.      ...
  945.   end func
  946.   
  947.  
  948. You may find this method of declaring local variables, whether to
  949. override or  to protect  the values of higher level variables, to
  950. be useful within your own programs.
  951.  
  952. 3.2.4 Help in menus
  953.  
  954.   RAP's menu-construct  has a  built-in help mechanism.  The code
  955. following the  help statement is executed if the user responds to
  956. the query  with ?  or help.  You can integrate this with the help
  957. topic system  of COMMON  by calling explain from the help section
  958. of a  menu-construct.   You may  want to  declare a local copy of
  959. #verbose so  the explanation  is not  affected by  if the  global
  960. version is set to zero.  For instance,
  961.  
  962.   
  963.   proc do_glossing
  964.   
  965.      declare #verbose
  966.      #verbose = 1
  967.   
  968.      loop
  969.         menu: IT glossing menu
  970.   
  971.            option:Prepare a text for glossing
  972.               do_itprep
  973.   
  974.            option:Gloss a text
  975.               do_itp
  976.   
  977.            option:Return to main menu
  978.               return
  979.   
  980.            help:
  981.               explain("glossing_options")
  982.   
  983.         end menu
  984.      end loop
  985.   
  986.   end proc
  987.  
  988.  
  989. ----------------------------------------------------------------
  990.  
  991. Chapter 5
  992.  
  993.  
  994. REFERENCE SUMMARY OF THE COMMON SUBROUTINE LIBRARY
  995.  
  996.  
  997. This chapter  defines each  subroutine in the COMMON library in
  998. full detail.   The  subroutines are  listed alphabetically.  Each
  999. entry begins  a new  page.  Entries are headed by the name of the
  1000. subroutine, followed  by a  parenthesized list of parameters.  If
  1001. the subroutine is a function, its name is preceded by an asterisk
  1002. (*).   The parameter  names are  preceded by $ or #, depending on
  1003. whether they  are string  or numeric  values.   Consequently, the
  1004. entry header  looks like a call to the subroutine would look in a
  1005. RAP program.   The  entries are  organized  under  the  following
  1006. subheadings:
  1007.  
  1008. Description
  1009.  
  1010.   A description of the subroutine's function.
  1011.  
  1012. Parameters
  1013.  
  1014.   A list of all the parameters with a brief description of each.
  1015.  
  1016. Return value
  1017.  
  1018.   A description of the subroutine's return value.  None indicates
  1019.   that the  subroutine  is  a  procedure.    String  and  numeric
  1020.   functions are distinguished by wording which states whether the
  1021.   return value is a string or a number.
  1022.  
  1023. Global variables used
  1024.  
  1025.   A description  of any  global variables used or modified by the
  1026.   subroutine.
  1027.  
  1028. Remarks
  1029.  
  1030.   Any further information needed to properly use the subroutine.
  1031.  
  1032. User error handling
  1033.  
  1034.   A description of how the subroutine handles invalid user input,
  1035.   including an  explanation of  any  messages  generated  by  the
  1036.   subroutine.
  1037.  
  1038. Parameter validation
  1039.  
  1040.   A description  of any  checking the subroutine does for invalid
  1041.   parameter values.   If  there is  a particular  kind of invalid
  1042.   parameter which is not tested for, that is mentioned as well.
  1043.  
  1044. Example
  1045.  
  1046.   A brief example of using the subroutine.
  1047.  
  1048.  
  1049. _________________________________________________________________
  1050.  
  1051. *deletef($filespec)
  1052. _________________________________________________________________
  1053.  
  1054. Description
  1055.  
  1056.   Deletes $filespec  if possible, and reports the result by means
  1057.   of a  return value.   The file is deleted without informing the
  1058.   user or asking for confirmation.
  1059.  
  1060. Parameters
  1061.  
  1062.   $filespec the file to be deleted
  1063.  
  1064. Return value
  1065.  
  1066.   A number  which is  .READWRITE if  the  file  was  successfully
  1067.   deleted, .NOTFOUND  if it  did not  exist, or  .READONLY if the
  1068.   file exists and is read-only and thus cannot be deleted.
  1069.  
  1070. Remarks
  1071.  
  1072.   *Deletef is not interactive; no messages are displayed.
  1073.  
  1074.   Application programs should always use this function instead of
  1075.   using killf  directly.  The problem with using killf is that if
  1076.   the file  is read-only  or non-existent,  the  RAP  program  is
  1077.   aborted and the user is returned to the RAP immediate mode.
  1078.  
  1079.   A return  value of .READWRITE or .NOTFOUND means that the named
  1080.   file no  longer exists.  You can now use that name for creating
  1081.   a new  file.   A return  value of .READONLY means that the file
  1082.   could not  be deleted.   If you were to try using the RAP *open
  1083.   function to  create a  new file with that name, the RAP program
  1084.   would be  aborted and  the user  would be  returned to  the RAP
  1085.   immediate mode prompt.
  1086.  
  1087. Example
  1088.  
  1089.   ; ensure that the external program can write $outfile
  1090.   
  1091.   if (*deletef($outfile) == .READONLY)
  1092.      t:*chr(7)\
  1093.      t:We need to delete $outfile, but you've made it
  1094.      t:read-only.  Please rename the file, or delete it,
  1095.      t:and then re-run this program.
  1096.      foot
  1097.      bye
  1098.   else
  1099.      xs $program $infile $outfile
  1100.   end if
  1101.  
  1102.  
  1103. _________________________________________________________________
  1104.  
  1105. *delq($filespec)
  1106. _________________________________________________________________
  1107.  
  1108.  
  1109. Description
  1110.  
  1111.   If $filespec exists, query user before deleting it.
  1112.  
  1113. Parameters
  1114.  
  1115.   $filespec the file to be deleted
  1116.  
  1117. Return value
  1118.  
  1119.   A number  which is  .READWRITE if  the  file  was  successfully
  1120.   deleted, .NOTFOUND if no file existed, or .READONLY if the file
  1121.   is read-only or the user said not to delete it.
  1122.  
  1123. Remarks
  1124.  
  1125.   *Delq is  interactive.  It is like *deletef but differs in that
  1126.   it asks  the user's permission before deleting the file, rather
  1127.   than doing  so silently.   It also displays an error message if
  1128.   the file is read-only.
  1129.  
  1130.   A return  value of .READWRITE or .NOTFOUND means that the named
  1131.   file no  longer exists.  You can now use that name for creating
  1132.   a new  file.   A return  value of .READONLY means that the user
  1133.   did not  want to  delete the file, or else that it could not be
  1134.   deleted.
  1135.  
  1136. Example
  1137.  
  1138.   ; repeat until we get a valid output file
  1139.   loop
  1140.   
  1141.      $outfile=*get_filespec("Output file","","","","")
  1142.   
  1143.   until (*delq($outfile) <> .READONLY)
  1144.  
  1145.  
  1146. _________________________________________________________________
  1147.  
  1148. *ensure_dot($ext)
  1149. _________________________________________________________________
  1150.  
  1151.  
  1152. Description
  1153.  
  1154.   Ensures that  a non-null file name extension begins with a dot.
  1155.   If the  proposed extension  is the  null string, then no dot is
  1156.   added.
  1157.  
  1158. Parameters
  1159.  
  1160.   $ext      the extension to be regularized
  1161.  
  1162. Return value
  1163.  
  1164.   A string  which is an extension guaranteed to begin with a dot,
  1165.   or to be the null string.
  1166.  
  1167. Remarks
  1168.  
  1169.   *Ensure_dot does  not test  the extension  for validity.    Use
  1170.   *val_ext for that purpose.
  1171.  
  1172. Example
  1173.  
  1174.   $newext=*get_str("New extension",".TXT","extensions",0,4)
  1175.   $newext=*ensure_dot($newext)
  1176.  
  1177.  
  1178. _________________________________________________________________
  1179.  
  1180. ensure_space($drive,$subdir,#space)
  1181. _________________________________________________________________
  1182.  
  1183.  
  1184. Description
  1185.  
  1186.   Ensures that there is enough space for an output file.
  1187.  
  1188. Parameters
  1189.  
  1190.   $drive    the drive where the file will be written
  1191.   $subdir   the directory where the file will be written
  1192.   #space    the needed free space in kilobytes
  1193.  
  1194. Return value
  1195.  
  1196.   None.
  1197.  
  1198. Remarks
  1199.  
  1200.   If there are not at least #space kilobytes of free space on the
  1201.   named drive,  the user  is prompted to delete some files on the
  1202.   disk.   The user  can request  to see  a display of the current
  1203.   directory  by   typing  dir.     The  directory  shown  is  the
  1204.   subdirectory passed  as the  $subdir parameter.    A  different
  1205.   directory, or  a subset  of the  files in  a directory,  can be
  1206.   displayed by typing dir followed by a filespec.  The normal DOS
  1207.   wildcard characters (* and ?) are valid in these filespecs.
  1208.  
  1209.   The drive  is not  changed from  the drive  specified   in  the
  1210.   $drive parameter, even if the user references a different drive
  1211.   in a  filespec.   The subroutine is trying to ensure that there
  1212.   is space  on the  specified drive≡it would do no good to delete
  1213.   files from  a different  drive.   Instead, a warning message is
  1214.   displayed and no files are deleted.
  1215.  
  1216.   The #size  parameter is  expressed in terms of kilobytes.  Note
  1217.   that RAP's  built-in functions *filesize, *freesp, and *memfree
  1218.   work in  units of bytes, rather than kilobytes.  The programmer
  1219.   who wants to mix COMMON's high-level routines with direct calls
  1220.   to RAP's  built-in functions  must be  sure to  compensate.  To
  1221.   convert from kilobytes to bytes, multiply by 1024.  To round up
  1222.   from bytes  to the  nearest kilobyte,  add 1023  and divide  by
  1223.   1024.
  1224.  
  1225.   There are  some potential  dangers in  using this routine.  For
  1226.   example, it is possible for the user to delete a file which has
  1227.   already  been  validated  as  existing  by  *get_input_file  or
  1228.   *get_append_file.   The user may not have any unnecessary files
  1229.   on that  disk.  Or, the user may try to change disks when it is
  1230.   not safe  to do so (see mount_volume for a discussion of this).
  1231.   If the  user cannot  make enough  room, his only recourse is to
  1232.   abort the  RAP program  by typing  Ctrl-C, losing any data that
  1233.   has not  been written  to a  file.  It is therefore recommended
  1234.   that this  procedure not  be called when a file is open or when
  1235.   information collected  by the  RAP program  has  not  yet  been
  1236.   written out.
  1237.  
  1238. User error handling
  1239.  
  1240.   If the  user enters  a drive designator as part of the filespec
  1241.   to delete,  a warning  message is  displayed, and  no files are
  1242.   deleted.   The user  is  then  prompted  to  re-enter  a  valid
  1243.   filespec which contains no drive designation.
  1244.  
  1245. Example
  1246.  
  1247.   ; make sure there is 100K of free space on drive C:
  1248.   
  1249.   ensure_space("C:","",100)
  1250.  
  1251.  
  1252. _________________________________________________________________
  1253.  
  1254. explain($topic)
  1255. _________________________________________________________________
  1256.  
  1257.  
  1258. Description
  1259.  
  1260.   Displays help information for the given topic.
  1261.  
  1262. Parameters
  1263.  
  1264.   $topic    the topic about which help is desired
  1265.  
  1266. Return value
  1267.  
  1268.   None.
  1269.  
  1270. Global variables used
  1271.   #verbose  enables explanations if non-zero
  1272.  
  1273. Remarks
  1274.  
  1275.   See chapter  3 for details on how to create a help file and use
  1276.   explain in your programs.
  1277.  
  1278.   In order  for  explain  to  function  at  all,  you  must  have
  1279.   previously opened the help file using the subroutine open_help.
  1280.  
  1281. Parameter validation
  1282.  
  1283.   If the  help file  is not open, the message "Sorry, there is no
  1284.   help file available to this program" is displayed.
  1285.  
  1286.   If the  topic is  not found in the help-file index, the message
  1287.   "Sorry, there is no help for this topic" is displayed.  Neither
  1288.   of these  messages are treated as internal error messages (that
  1289.   is, they  do not  advise the user to exit as soon as possible).
  1290.   An invalid  help-topic is  primarily an  annoyance to the user,
  1291.   not an indication that the program is likely to produce invalid
  1292.   results.
  1293.  
  1294. Example
  1295.  
  1296.   if (*yes("Do you want an introduction to IT","n",""))
  1297.      explain("intro")
  1298.   end if
  1299.  
  1300.  
  1301. _________________________________________________________________
  1302.  
  1303. *get_ans($query,$default,$topic,#oblig)
  1304. _________________________________________________________________
  1305.  
  1306.  
  1307. Description
  1308.  
  1309.   Asks a  question, displaying  a default  response if  any,  and
  1310.   returns the  user's response.  Displays help information on the
  1311.   given topic if user enters ? or help.
  1312.  
  1313. Parameters
  1314.  
  1315.   $query    the question to ask
  1316.   $default  the default response ("", if none)
  1317.   $topic    the help topic ("", if none)
  1318.   #oblig    .YES if  answer is  required; .NO  if  null  response
  1319.             allowed.
  1320.  
  1321. Return value
  1322.  
  1323.   A string  which is  the user's  response to  the query.   If  a
  1324.   $default parameter  is supplied, that string is returned if the
  1325.   user simply hits Enter.
  1326.  
  1327. Remarks
  1328.  
  1329.   If the  $query parameter  does not  end with a question mark or
  1330.   colon, *get_ans  automatically appends a question mark.    If a
  1331.   non-null value  is specified  for $default,  its value enclosed
  1332.   within square brackets is added to the displayed query.
  1333.  
  1334.   *Get_ans should  not be  used to  get string responses from the
  1335.   user≡use *get_str for that purpose.  *Get_ans is intended to be
  1336.   used as  a building  block for subroutines similar to *get_str.
  1337.   (See example below.)
  1338.  
  1339. User error handling
  1340.  
  1341.   If #oblig  is .YES  and no  $default parameter is supplied, the
  1342.   user is  forced to  enter a  nonblank answer.  If the user only
  1343.   hits Enter  when it  is not allowed, the message "This question
  1344.   requires an  answer" is  displayed, and then the original query
  1345.   is redisplayed.
  1346.  
  1347.   If the  user enters  ? or  help when  no  $topic  parameter  is
  1348.   provided, the  message "There  is no help for this question" is
  1349.   displayed, and the query is redisplayed.
  1350.  
  1351.  
  1352. Example
  1353.  
  1354.   ; get a list of punctuation marks from the user.
  1355.   
  1356.   string func get_punctuation($query,$default,$topic)
  1357.   
  1358.   declare $answer
  1359.   
  1360.   loop
  1361.      $answer=get_ans($query,$default,$topic,.YES)
  1362.      if ($answer has "[ \\tA-Z1-9]"))
  1363.          error("Please enter punctuation characters only",+
  1364.             $topic)
  1365.      else
  1366.          return $answer
  1367.      end if
  1368.   end loop
  1369.   
  1370.   end func
  1371.  
  1372.  
  1373. _________________________________________________________________
  1374.  
  1375. *get_append_file($query,$defpath,$defname,$defext,$topic)
  1376. _________________________________________________________________
  1377.  
  1378.  
  1379. Description
  1380.  
  1381.   Gets the  name of  a file  for editing  or updating.    If  the
  1382.   requested file  does not  exist, *get_append_file  creates  it.
  1383.   Requires user to select another file or to rename the requested
  1384.   file if  it has  a .TMP  or .BAK extension.  If the user enters
  1385.   dir, or  dir followed by a filespec, the directory is displayed
  1386.   and the query is redisplayed.
  1387.  
  1388. Parameters
  1389.  
  1390.   $query    the question to ask
  1391.   $defpath  default drive and subdirectory path
  1392.   $defname  default file name (without extension)
  1393.   $defext   default file extension
  1394.   $topic    the help topic ("", if no help)
  1395.  
  1396. Return value
  1397.  
  1398.   A string which is the filespec of a suitable file.
  1399.  
  1400. Global variables used
  1401.  
  1402.   #filesize the size of the file in kilobytes
  1403.   $drive    the drive part of the returned filespec
  1404.   $subdir   the subdirectory part of the returned filespec
  1405.   $name     the name part of the returned filespec
  1406.   $ext      the extension part of the returned filespec
  1407.  
  1408. Remarks
  1409.  
  1410.   *Get_append_file does not open the file.  Its purpose is to get
  1411.   a filespec  which may  be used  with *open  or with an external
  1412.   program using xs or xcall.
  1413.  
  1414.   This subroutine  is similar to *get_input_file, except that the
  1415.   requested file  does not  need to exist.  It is appropriate for
  1416.   filespecs that  will be  used with  text  editors  and  similar
  1417.   applications.  The file on which an editor is invoked is not an
  1418.   input file,  because if  the file  does not  exist it  will  be
  1419.   created, and  if the  file already exists it gets written to as
  1420.   well  as   read  from.  On  the  other  hand,  you  cannot  use
  1421.   *get_output_file  to   get  such   a  filespec,   because  that
  1422.   subroutine deletes the requested file if it already exists.
  1423.  
  1424.   *Get_append_file creates  an empty  file if  the requested file
  1425.   does not exist.
  1426.  
  1427.   See the  remarks under  *get_filespec for  the  constraints  on
  1428.   values of  the default filespec parameters ($defpath, $defname,
  1429.   and $defext),  and  for  an  explanation  of  exactly  what  is
  1430.   returned  in   the  four  global  filespec  variables  ($drive,
  1431.   $subdir, $name, and $ext).
  1432.  
  1433.   The file  size returned  in #filesize  is  rounded  up  to  the
  1434.   nearest  kilobyte.     Note   that  RAP's   built-in  functions
  1435.   *filesize, *freesp, and *memfree work in units of bytes, rather
  1436.   than kilobytes.  The programmer who wants to mix COMMON's high-
  1437.   level routines  with direct  calls to  RAP's built-in functions
  1438.   must be  sure to  compensate.   To convert  from  kilobytes  to
  1439.   bytes, multiply by 1024.  To round up from bytes to the nearest
  1440.   kilobyte, add 1023 and divide by 1024.
  1441.  
  1442. User error handling
  1443.  
  1444.   The requested file cannot be read-only.  If it is, a message is
  1445.   displayed and  the user  is allowed  to enter another filespec.
  1446.   The requested  file cannot have the extension .TMP or .BAK.  If
  1447.   it does,  a message  is displayed  and the  user is  allowed to
  1448.   rename the  file to  a different  extension or  to enter  a new
  1449.   filespec.
  1450.  
  1451. Example
  1452.  
  1453.   
  1454.   ; use text editor to enter free-form text
  1455.   
  1456.   $file=*get_append_file("File to edit","","","","")
  1457.   xs ed $file
  1458.   
  1459.  
  1460.  
  1461. _________________________________________________________________
  1462.  
  1463. *get_code($query,$default,$topic,#minlen,#maxlen)
  1464. _________________________________________________________________
  1465.  
  1466.  
  1467. Description
  1468.  
  1469.   Gets a  slash code (standard format marker) from the user.  The
  1470.   return value does not contain the backslash.
  1471.  
  1472. Parameters
  1473.  
  1474.   $query    the question to ask
  1475.   $default  the default response ("", if none)
  1476.   $topic    the help topic ("", if none)
  1477.   #minlen   minimum code length (must be 0 or greater)
  1478.   #maxlen   maximum code length (must be 1 or greater)
  1479.  
  1480. Return value
  1481.  
  1482.   A string which is the slash code without an initial backslash.
  1483.  
  1484. Remarks
  1485.  
  1486.   The code  must be  made up  of letters, digits, or underscores.
  1487.   No other  characters are  allowed.  The length of the code, not
  1488.   counting the  backslash, must  be between  #minlen and  #maxlen
  1489.   characters, inclusive.
  1490.  
  1491.   If the  default does  not begin  with a backslash, one is added
  1492.   when it is displayed.
  1493.  
  1494.   To make  an answer  obligatory, set  #minlen to a value of 1 or
  1495.   greater.
  1496.  
  1497. User error handling
  1498.  
  1499.   The following error conditions are detected: invalid characters
  1500.   in code,  code too  long or  too short,  and null response when
  1501.   #minlen is greater than zero.  If an error occurs, a message is
  1502.   displayed and the user is required to try again.
  1503.  
  1504. Parameter validation
  1505.  
  1506.   If #maxlen  is greater than the constant .MAXCODE, then #maxlen
  1507.   is reset  to .MAXCODE.   No  error message is displayed in this
  1508.   case.
  1509.  
  1510.   If #minlen  is greater  than #maxlen,  #minlen  is  set  to  1,
  1511.   #maxlen is  set  to  80,  and  an  internal  error  message  is
  1512.   displayed.
  1513.  
  1514.   No other  parameter  validation  is  done.    If  the  $default
  1515.   parameter contains  invalid characters or is outside the length
  1516.   limits, the error will be detected as a user error.
  1517.  
  1518. Example
  1519.  
  1520.   ; get a slash code from the user with a default value of
  1521.   ;   'w', and a length from 1 to 8 characters
  1522.   
  1523.   $record_marker=*get_code("Record marker","w",+
  1524.      "recmark",1,8)
  1525.  
  1526.  
  1527. _________________________________________________________________
  1528.  
  1529. *get_filespec($query,$defpath,$defname,$defext,$topic)
  1530. _________________________________________________________________
  1531.  
  1532.  
  1533. Description
  1534.  
  1535.   Gets a well-formed filespec from the user, using default values
  1536.   for any  parts that  the user  does not  supply.   If the  user
  1537.   enters dir,  or dir  followed by  a filespec,  the directory is
  1538.   displayed and the query is redisplayed.
  1539.  
  1540. Parameters
  1541.  
  1542.   $query    the question to ask
  1543.   $defpath  default drive and subdirectory path
  1544.   $defname  default file name (without extension)
  1545.   $defext   default file extension
  1546.   $topic    the help topic ("", if none)
  1547.  
  1548. Return value
  1549.  
  1550.   A string  which is  a well-formed  filespec containing drive, a
  1551.   subdirectory path, filename, and extension.
  1552.  
  1553. Global variables used
  1554.  
  1555.   $drive    the drive part of the returned filespec
  1556.   $subdir   the subdirectory part of the returned filespec
  1557.   $name     the name part of the returned filespec
  1558.   $ext      the extension part of the returned filespec
  1559.  
  1560. Remarks
  1561.  
  1562.   The parameters  which specify  the defaults  must be  formed as
  1563.   follows.   Any of them may also be a null string, in which case
  1564.   no default will be supplied for that part of the filespec.  See
  1565.   .FILECHARS on  page 14  for a  list of  the characters valid in
  1566.   subdirectory names, file names, and extensions.
  1567.  
  1568.   $defpath  A  drive   designator   including   colon   (A:),   a
  1569.             subdirectory list  optionally ending with a backslash
  1570.             (my\sub\dir\),   or    a   drive   and   subdirectory
  1571.             (C:\some\dir).   If the  colon is  left off  a  drive
  1572.             designator, it  will be interpreted as a subdirectory
  1573.             name.   For example, in C\some\dir, the C refers to a
  1574.             directory on the current drive, not to drive C:.
  1575.  
  1576.   $defname  A file  name  part  containing  one  to  eight  valid
  1577.             characters (my_file).  It must  not contain a leading
  1578.             colon or backslash, or a trailing dot.
  1579.  
  1580.   $defext   A file  extension containing one to three characters,
  1581.             with an  optional dot  at the beginning.  (The dot is
  1582.             not optional in the filespec, but the subroutine will
  1583.             add one for you if you omit it.)
  1584.  
  1585.   The returned  filespec is  parsed and  assigned to  the  global
  1586.   filespec variables as follows:
  1587.  
  1588.   $drive    Contains the  drive letter  and colon  (A:) or a null
  1589.             string if  the returned  filespec contains  no  drive
  1590.             specification.
  1591.  
  1592.   $subdir   Contains the  subdirectory list  from  the  filespec,
  1593.             including the  trailing backslash.  Contains the null
  1594.             string if the filespec has no subdirectory component.
  1595.  
  1596.   $name     Contains the filename part of the filespec.
  1597.  
  1598.   $ext      Contains  the   extension  part   of  the   filespec,
  1599.             including the  dot.   However, if  the user  enters a
  1600.             filespec that  contains no  extension or  dot, and no
  1601.             default is  supplied, then this variable will contain
  1602.             a null string.
  1603.  
  1604.   Note that  on return  from *get_filespec,  the values  of these
  1605.   four variables  are such that their concatenation is guaranteed
  1606.   to be  a valid  filespec.  In fact, $drive$subdir$name$ext will
  1607.   have exactly  the  same  value  as  the  return  value  of  the
  1608.   function.
  1609.  
  1610.   Note, too, that *get_filespec does not check to see if the file
  1611.   actually exists.   Use *get_input_file to confirm the existence
  1612.   of an input file.
  1613.  
  1614. User error handling
  1615.  
  1616.   The user's reply must be a well-formed filespec.  If it is not,
  1617.   the user receives a message explaining which part (or parts) of
  1618.   the filespec  were not  valid, and is then required to re-enter
  1619.   the filespec.
  1620.  
  1621. Example
  1622.  
  1623.   ; get a filespec and form a name with a different
  1624.   ; extension (as defined in .NEW)
  1625.   ;
  1626.   
  1627.   $oldfile=*get_filespec("File name","","","","")
  1628.   
  1629.   $newfile=$drive$subdir$name.NEW
  1630.  
  1631.  
  1632. _________________________________________________________________
  1633.  
  1634. *get_fixed_output($filespec,#size,#allow_sub,$query,$topic)
  1635. _________________________________________________________________
  1636.  
  1637.  
  1638. Description
  1639.  
  1640.   Get the  name of  a valid  file for  output, using a predefined
  1641.   name if  possible.  If the named file cannot be created, inform
  1642.   the user  and optionally get a substitute name.  The subroutine
  1643.   ensures that  there is  enough space for the file on the output
  1644.   device.
  1645.  
  1646. Parameters
  1647.   $filespec    filespec for proposed file name and location
  1648.   #size        size required (in kilobytes); 0, if no requirement
  1649.   #allow_sub   .YES if the user can supply an alternate name; .NO
  1650.                otherwise
  1651.   $query       question to ask if the user needs to supply new
  1652.                name
  1653.   $topic       the help topic ("", if none)
  1654.  
  1655. Return value
  1656.  
  1657.   A string which is the validated filespec of the output file.
  1658.  
  1659. Global variables used
  1660.  
  1661.   $drive    the drive part of the returned filespec
  1662.   $subdir   the subdirectory part of the returned filespec
  1663.   $name     the name part of the returned filespec
  1664.   $ext      the extension part of the returned filespec
  1665.  
  1666. Remarks
  1667.  
  1668.   This subroutine  is used when the programmer needs a predefined
  1669.   or "fixed"  filename to  communicate  between  programs.    For
  1670.   example, the  sample program in chapter 4 dynamically generates
  1671.   and runs  a PTP  program.  The user should not be bothered with
  1672.   supplying a  filename for this intermediate file.  On the other
  1673.   hand, rather  than going  ahead and  simply using  *open with a
  1674.   hard-coded filespec,  a  RAP  program  should  check  that  the
  1675.   filespec is  well-formed, that there is available disk space to
  1676.   create the  file, and that the file does not exist already as a
  1677.   read-only file.  *Get_fixed_output is meant for such files.
  1678.  
  1679.   If a  file matching  $filespec already  exists, it  is  deleted
  1680.   without interacting with the user.
  1681.  
  1682.   If the  #size parameter is greater than zero, *get_fixed_output
  1683.   ensures that  there are  at least #size kilobytes of free space
  1684.   on the output drive.  If there is not enough space, the user is
  1685.   requested to  delete some  files.   This is done by means of an
  1686.   internal call to ensure_space; see the entry for that procedure
  1687.   for a  description of  the behavior and potential risks of this
  1688.   operation.   Because of  these risks,  you are  advised to call
  1689.   *get_fixed_output either  before the user has entered extensive
  1690.   data, or  after such  data has  been written  to a file and the
  1691.   file has been closed.
  1692.  
  1693.   If *get_fixed_output  cannot succeed  because the proposed file
  1694.   exists already  as a  read-only file,  the user is informed and
  1695.   optionally prompted for a different filespec.  Normally you can
  1696.   allow the  user to supply an alternate filespec.  Occasionally,
  1697.   however, programs  do require  an exact filename.  For example,
  1698.   user-defined characters  for the  JAARS ED program (JAARS 1985)
  1699.   must be  in a  file named ED.CHR.  In such cases the #allow_sub
  1700.   parameter should  be set  to .NO.   When  #allow_sub  is  .YES,
  1701.   $query is  used for  the interactive prompt, and $topic defines
  1702.   the relevant help topic should the user to ? or help to ask for
  1703.   help on that prompt.
  1704.  
  1705.   If substitution is not allowed and the subroutine finds that an
  1706.   output file of the required name cannot be opened, then the RAP
  1707.   program cannot  successfully  proceed.    Therefore,  an  error
  1708.   message identifying  the write-locked file is displayed and the
  1709.   RAP program is terminated.  If $topic is defined, the help text
  1710.   for that  topic is  first displayed in order to give the user a
  1711.   context-sensitive explanation  of what  went wrong  and how  it
  1712.   might be  fixed.   Thus when  #allow_sub is .NO, the help topic
  1713.   functions as  a context-sensitive  error message, rather than a
  1714.   user-requested explanation.
  1715.  
  1716.   *Get_fixed_output does  not open  the file.   Its purpose is to
  1717.   get a filespec which may be used with *open or with an external
  1718.   program using xs or xcall.
  1719.  
  1720.   See the  remarks under *get_filespec for an explanation of what
  1721.   is returned  in the  four global  filespec  variables  ($drive,
  1722.   $subdir, $name, and $ext).
  1723.  
  1724.   The subroutine to get a fixed input file is mount_file.
  1725.  
  1726.  
  1727. Example
  1728.  
  1729.   ; Extract selected records, then format them.
  1730.   ; Selected records are first written to $intermediate,
  1731.   ; which becomes the input file for the formatting table.
  1732.   
  1733.   $infile=*get_input_file("Input file","","","","")
  1734.   $orig_name=$name
  1735.   
  1736.   $filespec=$drive$subdir\EXTRACT.OUT
  1737.   $intermediate=*get_fixed_output($filespec,#filesize,+
  1738.                   .YES,"Temporary file","")
  1739.   
  1740.   $outfile=*get_output_file("Output file",$drive$subdir,+
  1741.                   $orig_name,".OUT",#filesize)
  1742.   
  1743.   xcall cc -t extract.cct -o $intermediate $infile
  1744.   xcall ms -t exformat.cct -o $outfile $intermediate
  1745.   xs    del $intermediate
  1746.   
  1747.  
  1748.  
  1749. _________________________________________________________________
  1750.  
  1751. *get_input_file($query,$defpath,$defname,$defext,$topic)
  1752. _________________________________________________________________
  1753.  
  1754.  
  1755. Description
  1756.  
  1757.   Gets the  name  of  an  existing  file  for  input.    Displays
  1758.   directory if  user enters  dir, or  dir followed by a filespec.
  1759.   Requires user  to select  another file or to rename the file if
  1760.   the requested  input file  has .TMP  or .BAK extension.  If the
  1761.   user enters  dir, or  dir followed by a filespec, the directory
  1762.   is displayed and the query is redisplayed.
  1763.  
  1764. Parameters
  1765.  
  1766.   $query    the question to ask
  1767.   $defpath  default drive and subdirectory path
  1768.   $defname  default file name (without extension)
  1769.   $defext   default file extension
  1770.   $topic    the help topic ("", if none)
  1771.  
  1772. Return value
  1773.  
  1774.   A string which is the filespec of an existing input file.
  1775.  
  1776. Global variables used
  1777.  
  1778.   #filesize the size of the input file in kilobytes
  1779.   $drive    the drive part of the returned filespec
  1780.   $subdir   the subdirectory part of the returned filespec
  1781.   $name     the name part of the returned filespec
  1782.   $ext      the extension part of the returned filespec
  1783.  
  1784. Remarks
  1785.  
  1786.   This subroutine  does not open the file.  Its purpose is to get
  1787.   a valid  filespec of  an existing  file which  may be used with
  1788.   *open or with an external program using xs or xcall.
  1789.  
  1790.   See the  remarks under  *get_filespec for  the  constraints  on
  1791.   values of  the default filespec parameters ($defpath, $defname,
  1792.   and $defext),  and  for  an  explanation  of  exactly  what  is
  1793.   returned  in   the  four  global  filespec  variables  ($drive,
  1794.   $subdir, $name, and $ext).
  1795.  
  1796.   The file  size returned  in #filesize  is  rounded  up  to  the
  1797.   nearest  kilobyte.     Note   that  RAP's   built-in  functions
  1798.   *filesize, *freesp, and *memfree work in units of bytes, rather
  1799.   than kilobytes.  The programmer who wants to mix COMMON's high-
  1800.   level routines  with direct  calls to  RAP's built-in functions
  1801.   must be  sure to  compensate.   To convert  from  kilobytes  to
  1802.   bytes, multiply by 1024.  To round up from bytes to the nearest
  1803.   kilobyte, add 1023 and divide by 1024.
  1804.  
  1805. User error handling
  1806.  
  1807.   The user  must enter  the name of an already-existing file.  If
  1808.   the named  file does  not exist,  an error message is displayed
  1809.   and the  query is  redisplayed.   In addition,  the input  file
  1810.   cannot have  the extensions .BAK or .TMP.  If such an extension
  1811.   is entered,  the  user  is  given  the  choice  of  entering  a
  1812.   different filespec,  or of  renaming the .TMP or .BAK file to a
  1813.   different extension.   (This  function must  prohibit these two
  1814.   extensions in  order to  guarantee  that  *make_tmp_output  and
  1815.   make_bak_file will work on the input file.)
  1816.  
  1817. Example
  1818.  
  1819.   ; get file names, then open files
  1820.   
  1821.   $infile=*get_input_file("Input file","","","","")
  1822.   
  1823.   $outfile=*get_output_file("Output file",$drive$subdir,+
  1824.                              $name,".OUT",#filesize)
  1825.   
  1826.   #in = *open($infile)
  1827.   #out = *open($outfile,"w")
  1828.  
  1829.  
  1830. _________________________________________________________________
  1831.  
  1832. *get_num($query,$default,$topic,#min,#max)
  1833. _________________________________________________________________
  1834.  
  1835.  
  1836. Description
  1837.  
  1838.   Gets a  numeric answer  from  the  user.    A  default  may  be
  1839.   supplied, and  the answer  is forced  to be  within minimum and
  1840.   maximum limits.
  1841.  
  1842. Parameters
  1843.  
  1844.   $query    the question to ask
  1845.   $default  the default response ("", if none)
  1846.   $topic    the help topic ("", if none)
  1847.   #min      minimum value allowed
  1848.   #max      maximum value allowed
  1849.  
  1850. Return value
  1851.  
  1852.   A number  which is the value of the user's response, guaranteed
  1853.   to  be  between  the  specified  minimum  and  maximum  values,
  1854.   inclusive.
  1855.  
  1856. Remarks
  1857.  
  1858.   Note that  the default  is a  string variable,  not  a  numeric
  1859.   variable.   This is so the subroutine can distinguish between a
  1860.   default of  "0" (that  is, return  0 if  the user  only presses
  1861.   Enter) and  "no default"  (that is,  the user cannot just press
  1862.   Enter).   #Min and  #max can be effectively disabled by setting
  1863.   them to the smallest and largest numeric values allowed by RAP.
  1864.   Instead of  using literal  numbers in  your  program  for  this
  1865.   purpose, use  the symbolic  values .MININT  and .MAXINT.  Using
  1866.   the symbolic  values means  your program  will not  have to  be
  1867.   revised if  a future  version  of  RAP  allows  larger  numeric
  1868.   variables.
  1869.  
  1870. User error handling
  1871.  
  1872.   The following  error  conditions  are  detected:  input  not  a
  1873.   number, input  out of  range (that  is, not  between  #min  and
  1874.   #max), and  null response when no default is supplied.  In each
  1875.   case  an   error  message   is  displayed,  and  the  query  is
  1876.   redisplayed.
  1877.  
  1878.  
  1879. Parameter validation
  1880.  
  1881.   If #min  is greater  than #max,  #min and  #max are  set to the
  1882.   smallest and  largest values  RAP allows, and an internal error
  1883.   message is displayed.
  1884.  
  1885.   If a  default is  supplied that  is  not  a  valid  number,  an
  1886.   internal error  message is displayed and $default is changed to
  1887.   a null string (that is, no default).
  1888.  
  1889. Example
  1890.  
  1891.   ; get page length, with a default of 66,
  1892.   ;   minimum of 20, and maximum of 132
  1893.   
  1894.   #page_length=*get_num("Page length","66",$topic,20,132)
  1895.  
  1896.  
  1897. _________________________________________________________________
  1898.  
  1899. *get_output_file($query,$defpath,$defname,$defext,$topic,#size)
  1900. _________________________________________________________________
  1901.  
  1902.  
  1903. Description
  1904.  
  1905.   Get the  name of  a valid  file for  output.  If the named file
  1906.   already exists,  the  user  must  confirm  that  it  should  be
  1907.   overwritten.   The subroutine also ensures that there is enough
  1908.   space for  the file  on the  output device.  If the user enters
  1909.   dir, or  dir followed by a filespec, the directory is displayed
  1910.   and the query is redisplayed.
  1911.  
  1912. Parameters
  1913.  
  1914.   $query    the question to ask
  1915.   $defpath  default drive and subdirectory path
  1916.   $defname  default file name (without extension)
  1917.   $defext   default file extension
  1918.   $topic    the help topic ("", if none)
  1919.   #size     size required (in kilobytes);  0, if no requirement
  1920.  
  1921. Return value
  1922.  
  1923.   A string which is the validated filespec of the output file.
  1924.  
  1925. Global variables used
  1926.  
  1927.   $drive    the drive part of the returned filespec
  1928.   $subdir   the subdirectory part of the returned filespec
  1929.   $name     the name part of the returned filespec
  1930.   $ext      the extension part of the returned filespec
  1931.  
  1932. Remarks
  1933.  
  1934.   This subroutine  does not open the file.  Its purpose is to get
  1935.   a filespec  which may  be used  with *open  or with an external
  1936.   program executed by means of xs or xcall.
  1937.  
  1938.   See the  remarks under  *get_filespec for  the  constraints  on
  1939.   values of  the default filespec parameters ($defpath, $defname,
  1940.   and $defext),  and  for  an  explanation  of  exactly  what  is
  1941.   returned  in   the  four  global  filespec  variables  ($drive,
  1942.   $subdir, $name, and $ext).
  1943.  
  1944.   If the  #size parameter  is greater  than zero,  the subroutine
  1945.   ensures that  there are  at least #size kilobytes of free space
  1946.   on the output drive.  If there is not enough space, the user is
  1947.   requested to  delete some  files.   This is done by means of an
  1948.   internal call to ensure_space; see the entry for that procedure
  1949.   for a  description of  the behavior and potential risks of this
  1950.   operation.   Because of  these risks,  you are  advised to call
  1951.   *get_output_file either  before the  user has entered extensive
  1952.   data, or  after such  data has  been written  to a file and the
  1953.   file has been closed.
  1954.  
  1955. Example
  1956.  
  1957.   ; Get file names and run the 'extract' change table.
  1958.   ; Suggested output file name is input file name with
  1959.   ;    .OUT extension.
  1960.   
  1961.   $infile=*get_input_file("Input file","","","","")
  1962.   
  1963.   $outfile=*get_output_file("Output file",$drive$subdir,+
  1964.                              $name,".OUT",#filesize)
  1965.   
  1966.   xcall cc -t extract.cct -o $outfile $infile
  1967.  
  1968.  
  1969. _________________________________________________________________
  1970.  
  1971. *get_str($query,$default,$topic,#minlen,#maxlen)
  1972. _________________________________________________________________
  1973.  
  1974.  
  1975. Description
  1976.  
  1977.   Gets a  string from the user.  A default answer may be returned
  1978.   if the  user just  hits Enter,  or the  user may be required to
  1979.   give an  explicit answer.   The  length of  the answer  must be
  1980.   between minimum and maximum limits.
  1981.  
  1982. Parameters
  1983.  
  1984.   $query    the question to ask
  1985.   $default  the default response ("", if none)
  1986.   $topic    the help topic ("", if none)
  1987.   #minlen   minimum string length (must be 0 or greater)
  1988.   #maxlen   maximum string length (must be 1 or greater)
  1989.  
  1990. Return value
  1991.  
  1992.   A string  which is  the user's answer.  If a $default parameter
  1993.   is supplied,  that string  is returned  if the user simply hits
  1994.   Enter.
  1995.  
  1996. Remarks
  1997.  
  1998.   To make a non-null answer obligatory, set #minlen to a value of
  1999.   1 or  more.   Note that  the user  may still  hit just Enter to
  2000.   select the  default, as long as the length of $default is equal
  2001.   to or greater than #minlen.
  2002.  
  2003.   To allow  the function  to return  a null string, you must both
  2004.   specify $default  as a  null string ("") and specify #minlen as
  2005.   0.   It is  then possible for the user to give a null answer by
  2006.   pressing Enter.
  2007.  
  2008.   To require  the  user  to  type  an  explicit  answer,  specify
  2009.   $default as a null string, but specify #minlen as 1 or greater,
  2010.   thus disabling the null default.
  2011.  
  2012. User error handling
  2013.  
  2014.   If the  answer is too short or too long, a message is displayed
  2015.   and the user must try again.
  2016.  
  2017. Parameter validation
  2018.  
  2019.   If #minlen  is greater  than #maxlen,  #minlen  is  set  to  1,
  2020.   #maxlen is  set  to  80,  and  an  internal  error  message  is
  2021.   displayed.
  2022.  
  2023.   If a  default is  supplied, but  #minlen is greater than 0, the
  2024.   user will  be unable  to select  the default by pressing Enter.
  2025.   No test is made for this error.
  2026.  
  2027. Example
  2028.  
  2029.   ; get user's name:  a response is obligatory
  2030.   ; and limited to 60 characters
  2031.   
  2032.   $name=*get_str("What is your name","","",1,60)
  2033.  
  2034.  
  2035. _________________________________________________________________
  2036.  
  2037. kbflush()
  2038. _________________________________________________________________
  2039.  
  2040.  
  2041. Description
  2042.  
  2043.   Flushes the type-ahead buffer.
  2044.  
  2045. Parameters
  2046.  
  2047.   None.
  2048.  
  2049. Return value
  2050.  
  2051.   None.
  2052.  
  2053. Remarks
  2054.  
  2055.   Kbflush is  used to ensure that subsequent keyboard input comes
  2056.   after a  certain point  in the  program,  not  from  type-ahead
  2057.   input.   As the  example below illustrates, there are instances
  2058.   in which  input that has been typed ahead (whether purposely or
  2059.   inadvertently)  could   have  disastrous  results.    Executing
  2060.   kbflush right  before a  query allows the programmer to be sure
  2061.   that the  response is  the user's  answer to that question, and
  2062.   not an accidental type ahead.
  2063.  
  2064. Example
  2065.  
  2066.   kbflush()
  2067.   if (*yes("Do you want to delete all files on drive +
  2068.         A:","",""))
  2069.      xs del a:*.*
  2070.   end if
  2071.  
  2072.   Here is an even safer version of the same thing, especially for
  2073.   systems with slow display speed:
  2074.  
  2075.   t:Do you want to delete all files on drive A:\
  2076.   kbflush()
  2077.   if (*yes("","",""))
  2078.         xs del a:*.*
  2079.   end if
  2080.  
  2081.  
  2082. _________________________________________________________________
  2083.  
  2084. make_bak_file($permname,$tmpname)
  2085. _________________________________________________________________
  2086.  
  2087.  
  2088. Description
  2089.  
  2090.   Updates a  temporary file.   The existing .BAK file, if any, is
  2091.   deleted; the  existing copy  of $permname  is renamed as a .BAK
  2092.   file; and the temporary file $tmpname is renamed as $permname.
  2093.  
  2094. Parameters
  2095.  
  2096.   $permname the name of the permanent copy of the file
  2097.   $tmpname  the name of the temporary file
  2098.  
  2099. Return value
  2100.  
  2101.   None.
  2102.  
  2103. Remarks
  2104.  
  2105.   This subroutine  assumes that  the file  in $permname  does not
  2106.   have the  extension .BAK, and that the file in $tmpname has the
  2107.   extension .TMP.   These  conditions can  be  ensured  by  using
  2108.   *get_input_file to  get $permname  and *make_tmp_output  to get
  2109.   $tmpname.
  2110.  
  2111. User error handling
  2112.  
  2113.   An existing  .BAK file  must be deleted by this subroutine.  If
  2114.   the existing  .BAK file  is  read-only,  an  error  message  is
  2115.   displayed and the update is not performed.
  2116.  
  2117. Example
  2118.  
  2119.   ; get file to be reformatted
  2120.   $infile=*get_input_file("Input file","","",+
  2121.      ".TXT","reformat")
  2122.   
  2123.   ; get temporary output file
  2124.   $tmpfile=*make_tmp_output($infile,#filesize)
  2125.   
  2126.   ; do the reformatting
  2127.   xs cc -t reformat.cct -o $tmpfile $infile
  2128.   
  2129.   ; give the reformatted file the original name
  2130.   make_bak_file($infile,$tmpfile)
  2131.  
  2132.  
  2133. _________________________________________________________________
  2134.  
  2135. make_bak_to_bat($permname,$tmpname,#bat)
  2136. _________________________________________________________________
  2137.  
  2138.  
  2139. Description
  2140.  
  2141.   Creates batch  file lines  to perform  a temporary file update.
  2142.   The existing  .BAK file,  if any, is deleted; the existing copy
  2143.   of $permname  is renamed as a .BAK file; and the temporary file
  2144.   $tmpname is renamed as $permname.
  2145.  
  2146. Parameters
  2147.  
  2148.   $permname the name of the permanent copy of the file
  2149.   $tmpname  the name of the temporary file
  2150.   #bat      the file descriptor for the batch file to write
  2151.  
  2152. Return value
  2153.  
  2154.   None.
  2155.  
  2156. Remarks
  2157.  
  2158.   This subroutine  assumes that  the file  in $permname  does not
  2159.   have the  extension .BAK, and that the file in $tmpname has the
  2160.   extension .TMP.   These  conditions can  be  ensured  by  using
  2161.   *get_input_file to  get $permname  and *make_tmp_output  to get
  2162.   $tmpname.
  2163.  
  2164. Parameter validation
  2165.  
  2166.   Because the  update of  file names is done by a batch file, RAP
  2167.   cannot provide  any error  messages, nor can it easily find out
  2168.   if the  update failed.   If an existing .BAK file is read-only,
  2169.   COMMAND.COM will  generate  the  following  sequence  of  error
  2170.   messages on  the screen,  but they may not remain on the screen
  2171.   long enough for the user to notice them.
  2172.  
  2173.      File not found (or Access denied)
  2174.      Duplicate file name or File not found
  2175.      Duplicate file name or File not found
  2176.  
  2177.  
  2178.  
  2179. Example
  2180.  
  2181.   ; RAP is run from a batch file called GO.BAT
  2182.   ; containing:
  2183.   ;     RAP MY_PROG
  2184.   ;     DOIT
  2185.   ; The RAP program writes DOIT.BAT, then GO.BAT
  2186.   ; automatically chains to it when RAP exits
  2187.   
  2188.   #bat = *open("doit.bat","w")
  2189.   
  2190.   ; get input file and temporary output
  2191.   $infile=*get_input_file("Input file","","",+
  2192.      ".TXT","reformat")
  2193.   $tmpfile=*make_tmp_output($infile,#filesize)
  2194.   
  2195.   ; write command line to do the reformatting
  2196.   wr #bat, xs cc -t reformat.cct -o $tmpfile $infile
  2197.   
  2198.   ; generate batch file commands to create the backup file
  2199.   make_bak_to_bat($infile,$tmpfile,#bat)
  2200.   
  2201.   closef #bat
  2202.   
  2203.   bye   ; and execute the batch
  2204.         ; file we just created.
  2205.  
  2206.  
  2207. _________________________________________________________________
  2208.  
  2209. *make_tmp_output($filespec,#size)
  2210. _________________________________________________________________
  2211.  
  2212.  
  2213. Description
  2214.  
  2215.   Creates a  .TMP file  name based  on the  file name given as an
  2216.   input parameter, and ensures that there is sufficient space for
  2217.   the .TMP file to be written.
  2218.  
  2219. Parameters
  2220.  
  2221.   $filespec the filespec for the base file
  2222.   #size     size required (in kilobytes);  0, if no requirement
  2223.  
  2224. Return value
  2225.  
  2226.   A string  which is the filespec of the .TMP file which is valid
  2227.   for output.
  2228.  
  2229. Remarks
  2230.  
  2231.   This subroutine  does not  open the  file.   Its purpose  is to
  2232.   produce a  filespec which  may be  used with  *open or  with an
  2233.   external program executed by means of xs or xcall.
  2234.  
  2235.   This subroutine  assumes that  $filespec is a valid input file,
  2236.   and that  it does  not have  the extension  .TMP.  These can be
  2237.   ensured by  always calling *get_input_file first, and using the
  2238.   filespec it returns as the filespec for *make_tmp_output.
  2239.  
  2240.   If there  is already another file with the resulting .TMP name,
  2241.   it is deleted without asking the user.  If such a file is read-
  2242.   only  (and   thus  cannot  be  deleted)  an  error  message  is
  2243.   displayed.
  2244.  
  2245.   If the  #size parameter  is greater than zero, *make_tmp_output
  2246.   ensures that  there are  at least #size kilobytes of free space
  2247.   on the output drive.  If there is not enough space, the user is
  2248.   requested to  delete some  files.   This is done by means of an
  2249.   internal call to ensure_space; see the entry for that procedure
  2250.   for a  description of  the behavior and potential risks of this
  2251.   operation.   Because of  these risks,  you are  advised to call
  2252.   *make_tmp_output either  before the  user has entered extensive
  2253.   data, or  after such  data has  been written  to a file and the
  2254.   file has been closed.
  2255.  
  2256.   If the  #size parameter  is greater  than zero,  the subroutine
  2257.   ensures that there is at least #size kilobytes of free space on
  2258.   the output  device.   If there is not enough space, the user is
  2259.   required to  delete some  files from  the device.   This  is  a
  2260.   potentially risky  proposition:  the  user  may  not  have  any
  2261.   unnecessary files  on that  disk!  Nor does the program know if
  2262.   it is  safe to  change disks at that point.  If the user cannot
  2263.   make enough room, his only recourse is to abort the RAP program
  2264.   by typing  Ctrl-C, which  will lose  any data that has not been
  2265.   written to  a file.   The behavior of this subroutine is likely
  2266.   to be  revised in  future versions.   In  the meantime, you are
  2267.   advised to  call *make_tmp_output  either before  the user  has
  2268.   entered extensive  data, or after such data has been written to
  2269.   a file and the file has been closed.
  2270.  
  2271. Example
  2272.  
  2273.   ;the CC table will probably double the size
  2274.   ; of the input file
  2275.   
  2276.   $infile=*get_input_file("Input file","","","","")
  2277.   $tmpfile=*make_tmp_output($infile,  #filesize * 2)
  2278.   
  2279.   xcall cc -t process.cct -o $tmpfile $infile
  2280.  
  2281.  
  2282. _________________________________________________________________
  2283.  
  2284. message($text)
  2285. _________________________________________________________________
  2286.  
  2287.  
  2288. Description
  2289.  
  2290.   Rings the  bell, displays  a message,  flushes  the  type-ahead
  2291.   buffer, and waits until the user presses Enter.
  2292.  
  2293. Parameters
  2294.  
  2295.   $text     the message to display
  2296.  
  2297. Return value
  2298.  
  2299.   None.
  2300.  
  2301. Remarks
  2302.  
  2303.   The  keyboard  buffer  is  flushed  to  ensure  that  the  foot
  2304.   statement, used  internally to  pause the screen, is terminated
  2305.   by the  user responding to the message, rather than by any type
  2306.   ahead.
  2307.  
  2308.   To indent the message, include leading spaces in $text.
  2309.  
  2310. Example
  2311.  
  2312.   message("Be sure the printer is turned on and the paper +
  2313.                is lined up.")
  2314.  
  2315.  
  2316. _________________________________________________________________
  2317.  
  2318. mount_file($filespec,$topic)
  2319. _________________________________________________________________
  2320.  
  2321.  
  2322. Description
  2323.  
  2324.   Ensures that  the specified  file is  mounted and available for
  2325.   use.  Prompts user to change disks, if necessary and if safe to
  2326.   do so.
  2327.  
  2328. Parameters
  2329.  
  2330.   $filespec filespec for name and location of file
  2331.   $topic    the help topic ("", if none)
  2332.  
  2333. Return value
  2334.  
  2335.   None.
  2336.  
  2337. Global variables used
  2338.  
  2339.   #filesize the size of the file in kilobytes
  2340.   $drive    the drive part of the filespec
  2341.   $subdir   the subdirectory part of the filespec
  2342.   $name     the name part of the filespec
  2343.   $ext      the extension part of the filespec
  2344.  
  2345. Remarks
  2346.  
  2347.   This subroutine  is used when the program must read a file with
  2348.   a predefined,  fixed name.   Rather  than going ahead to simply
  2349.   use *open  with a  hard-coded filespec,  a RAP  program  should
  2350.   ensure that  the file  is available  for input.   Mount_file is
  2351.   meant for  this purpose.  If this procedure succeeds, $filespec
  2352.   can then  be safely  used with  *open or  as a  parameter to an
  2353.   external program using xs or xcall.
  2354.  
  2355.   If the  file named  in $filespec cannot be found, then an error
  2356.   message identifying  the missing file and its expected location
  2357.   is displayed.   If  $topic is  defined, the  help text for that
  2358.   topic is  also displayed  in order  to give the user a context-
  2359.   sensitive explanation of what went wrong.  If no files are open
  2360.   and it  is thus  safe to  change disks  (see  discussion  under
  2361.   mount_volume), the  procedure  invites  the  user  to  mount  a
  2362.   different disk  volume.   Otherwise,  the  RAP  program  cannot
  2363.   proceed and is terminated.  For this reason, it is best to call
  2364.   this procedure when no other files are open and before the user
  2365.   is  required   to  interact  with  the  RAP  program  to  enter
  2366.   information.
  2367.  
  2368.   Unlike RAP's  built-in *existf  function, which  uses the $path
  2369.   variable to  search a  number of  directories when the filespec
  2370.   specifies no  drive or  subdirectory path,  mount_file requires
  2371.   that the file be in the current directory if $filespec gives no
  2372.   location.  For this reason, mount_file should be used to verify
  2373.   the existence  of fixed-name  files for  use as  parameters  to
  2374.   external commands via xs or xcall.  Using *existf in such cases
  2375.   may give the wrong answer, since the DOS command processor will
  2376.   not search  the subdirectories in its PATH variable to look for
  2377.   data files.
  2378.  
  2379.   Besides ensuring  availability, this  subroutine has  the  side
  2380.   effect of returning the file size and parsing the filespec into
  2381.   its four  main components.  In this respect, mount_file is like
  2382.   the functions  for input and output files and fills the spot of
  2383.   a  get_fixed_input   function.      See   the   remarks   under
  2384.   *get_filespec for  an explanation  of what  is returned  in the
  2385.   four global  filespec variables  ($drive, $subdir,  $name,  and
  2386.   $ext).
  2387.  
  2388.   The file  size returned  in #filesize  is  rounded  up  to  the
  2389.   nearest  kilobyte.     Note   that  RAP's   built-in  functions
  2390.   *filesize, *freesp, and *memfree work in units of bytes, rather
  2391.   than kilobytes.  The programmer who wants to mix COMMON's high-
  2392.   level routines  with direct  calls to  RAP's built-in functions
  2393.   must be  sure to  compensate.   To convert  from  kilobytes  to
  2394.   bytes, multiply by 1024.  To round up from bytes to the nearest
  2395.   kilobyte, add 1023 and divide by 1024.
  2396.  
  2397. Example
  2398.  
  2399.   ; Read the user's config.sys to see if the system is
  2400.   ; configured adequately for our application
  2401.   
  2402.   mount_file("\\config.sys","")
  2403.   #config=*open("\\config.sys")
  2404.   ...
  2405.  
  2406.  
  2407. _________________________________________________________________
  2408.  
  2409. mount_program($filespec,$topic)
  2410. _________________________________________________________________
  2411.  
  2412.  
  2413. Description
  2414.  
  2415.   Ensures  that   the  specified  program  file  is  mounted  and
  2416.   available for  use.  Prompts user to change disks, if necessary
  2417.   and if safe to do so.
  2418.  
  2419. Parameters
  2420.  
  2421.   $filespec filespec for name and location of file
  2422.   $topic    the help topic ("", if none)
  2423.  
  2424. Return value
  2425.  
  2426.   None.
  2427.  
  2428. Remarks
  2429.  
  2430.   This subroutine  is used  when the  RAP  program  must  run  an
  2431.   external program.   Rather than going ahead and calling it with
  2432.   xs or  xcall, a  RAP program  should ensure  that the  external
  2433.   program is  available for use.  Mount_program is meant for this
  2434.   purpose.   If this  procedure succeeds,  $filespec can  then be
  2435.   safely used as an external program name in xs or xcall.
  2436.  
  2437.   If the  program named  in $filespec  cannot be  found, then  an
  2438.   error message  identifying the  missing file  and its  expected
  2439.   location is displayed.  If $topic is defined, the help text for
  2440.   that topic  is also  displayed in  order to  give  the  user  a
  2441.   context-sensitive explanation  of what went wrong.  If no files
  2442.   are open  and it  is thus  safe to change disks (see discussion
  2443.   under mount_volume),  the procedure invites the user to mount a
  2444.   different disk  volume.   Otherwise,  the  RAP  program  cannot
  2445.   proceed and is terminated.  For this reason, it is best to call
  2446.   this procedure when no other files are open and before the user
  2447.   is  required   to  interact  with  the  RAP  program  to  enter
  2448.   information.
  2449.  
  2450.   This procedure  uses the  $path variable  to search a number of
  2451.   directories when  $filespec specifies no drive or subdirectory.
  2452.   RAP initializes  $path to  the value  of DOS's  PATH  variable.
  2453.   Thus, as  long as  the RAP  program does not alter the value of
  2454.   $path, any  program name  validated by  mount_program  will  be
  2455.   successfully located  by the  DOS command  processor  when  the
  2456.   external command is executed.
  2457.  
  2458.  
  2459. Example
  2460.  
  2461.   ; Ensure that CC and PTPC are installed on the user's
  2462.   ; system before beginning to ask all the questions
  2463.   
  2464.   mount_program("CC.EXE","")
  2465.   mount_program("PTPC.EXE","")
  2466.   
  2467.  
  2468.  
  2469. _________________________________________________________________
  2470.  
  2471. mount_volume($drive,$id,$name)
  2472. _________________________________________________________________
  2473.  
  2474.  
  2475. Description
  2476.  
  2477.   Ensures that  the disk  volume mounted in a particular drive is
  2478.   the one needed.  Prompts user to change disks, if necessary and
  2479.   if safe to do so.
  2480.  
  2481. Parameters
  2482.  
  2483.   $drive    the drive to use
  2484.   $id       the volume ID of the desired disk
  2485.   $name     name of the desired disk (for display purposes)
  2486.  
  2487. Return value
  2488.  
  2489.   None.
  2490.  
  2491. Remarks
  2492.  
  2493.   If the  volume mounted  in $drive  does not have the given $id,
  2494.   then the  user is  asked to mount the volume.  The prompt given
  2495.   is "Place  the $name disk in drive $drive", in which the values
  2496.   of the $name and $drive parameters are substituted.  While that
  2497.   name could  be identical  to the volume ID on the disk, it need
  2498.   not be.   For  instance, $name  can exceed the eleven character
  2499.   length limit  of a volume ID in order to refer to the disk in a
  2500.   more natural way.
  2501.  
  2502.   Because current  versions of  MS-DOS are  not always  aware  of
  2503.   disks being  changed, it  is not safe to change a disk if there
  2504.   are files  open on  it.   In the  case of  an input  file,  the
  2505.   program might  go ahead and read garbage from the new disk.  In
  2506.   the case  of an  output file,  it is likely to destroy the File
  2507.   Allocation Table on the new disk when the file is closed.
  2508.  
  2509.   Unfortunately, a  RAP program cannot tell which drives any open
  2510.   files are on.  Nor is it possible to tell whether they are open
  2511.   for input  or for  output.   The best  we can  do is to know if
  2512.   there are any files open at all.  Therefore, to ensure complete
  2513.   safety, mount_volume requires that there are no open files.  If
  2514.   there are,  an internal  error message  is  displayed  and  the
  2515.   program terminates.   Programmers must therefore ensure that no
  2516.   files are open whenever mount_volume is called.  (The help file
  2517.   is an  exception; COMMON automatically takes care of that.)  In
  2518.   cases where  there is  a legitimate  need to  keep files on one
  2519.   disk open  while another  disk is replaced, the programmer must
  2520.   define   a    new   procedure    (and    assume    the    risks
  2521.   involved!)≡mount_volume will not allow a new disk to be mounted
  2522.   in that situation.
  2523.  
  2524. Example
  2525.  
  2526.   ; ensure that the IT program disk is in drive B:
  2527.   
  2528.   mount_volume("B:","IT_PROGS","IT Programs Disk")
  2529.  
  2530.  
  2531. _________________________________________________________________
  2532.  
  2533. *no($query,$default,$topic)
  2534. _________________________________________________________________
  2535.  
  2536.  
  2537. Description
  2538.  
  2539.   Tests if  the user  answers  no  to  the  query,  supplying  an
  2540.   optional default response.
  2541.  
  2542. Parameters
  2543.  
  2544.   $query    the question to ask
  2545.   $default  the default response ("", if none)
  2546.   $topic    the help topic ("", if none)
  2547.  
  2548. Return value
  2549.  
  2550.   A number  which is  .YES if the answer was no, or .NO if it was
  2551.   yes.
  2552.  
  2553. Remarks
  2554.  
  2555.   The user's response must be one of the following: y, yes, n, or
  2556.   no.  Case is ignored, as are leading or trailing blanks.
  2557.  
  2558. User error handling
  2559.  
  2560.   If an  invalid response  is given,  *no  displays  the  message
  2561.   "Please type yes or no" and redisplays the query.
  2562.  
  2563. Parameter validation
  2564.  
  2565.   *No does  not validate  $default before  using it.   This means
  2566.   that if  an invalid  $default was passed, it will be displayed,
  2567.   but the  user error handling will reject it if the user presses
  2568.   just Enter.
  2569.  
  2570. Example
  2571.  
  2572.   loop
  2573.      ...
  2574.         repeat if (*no("Is everything correct","",""))
  2575.      ...
  2576.   end loop
  2577.  
  2578.  
  2579. _________________________________________________________________
  2580.  
  2581. open_help($helpfile)
  2582. _________________________________________________________________
  2583.  
  2584.  
  2585. Description
  2586.  
  2587.   Opens the programmer-supplied help file for the RAP program.
  2588.  
  2589. Parameters
  2590.  
  2591.   $helpfile the name of the help file
  2592.  
  2593. Return value
  2594.  
  2595.   None.
  2596.  
  2597. Remarks
  2598.  
  2599.   The help  file name may be a simple filename or a full filespec
  2600.   (including drive  and subdirectory).   If  a simple filename is
  2601.   given, open_help  searches for  it on  the  default  directory,
  2602.   followed by  all directories listed in DOS's PATH variable.  If
  2603.   the filespec  includes a drive or subdirectory, open_help tries
  2604.   to find  the named  file  only  and  does  not  look  in  other
  2605.   locations.
  2606.  
  2607.   If the  help file cannot be found, the user is given the choice
  2608.   of entering  a new  filespec  for  the  help  file,  continuing
  2609.   without help available, or exiting the program.
  2610.  
  2611.   See chapter 3 for a full discussion of the help system provided
  2612.   by the COMMON subroutine library.
  2613.  
  2614. Example
  2615.  
  2616.   proc main
  2617.   
  2618.      open_help("demo.hlp")
  2619.   
  2620.      explain("intro_to_demo")
  2621.   
  2622.      ...
  2623.   
  2624.   end proc
  2625.  
  2626.  
  2627. _________________________________________________________________
  2628.  
  2629. *parse_filespec($filespec,#report)
  2630. _________________________________________________________________
  2631.  
  2632.  
  2633. Description
  2634.  
  2635.   Validates the  well-formedness of  a filespec,  and parses  the
  2636.   four components  of the filespec into the four global variables
  2637.   $drive,  $subdir,   $name,  and   $ext.    The  programmer  may
  2638.   optionally suppress the reporting of error messages.
  2639.  
  2640. Parameters
  2641.  
  2642.   $filespec the filespec to validate and parse
  2643.   #report   .YES, if  filespec errors  should be  reported to the
  2644.             screen; .NO, otherwise
  2645.  
  2646. Return value
  2647.  
  2648.   A number  which is  .YES if the filespec is well-formed, or .NO
  2649.   if it is not.
  2650.  
  2651. Global variables used
  2652.  
  2653.   $drive    the drive part of the returned filespec
  2654.   $subdir   the subdirectory part of the returned filespec
  2655.   $name     the name part of the returned filespec
  2656.   $ext      the extension part of the returned filespec
  2657.  
  2658. Remarks
  2659.  
  2660.   If the  return value is .NO, the values in the global variables
  2661.   are undefined.
  2662.  
  2663.   This procedure  makes no  attempt to  open the  file  named  in
  2664.   $filespec; nor  does it  test that  the file exists.  It merely
  2665.   tests if the filespec is syntactically well-formed.
  2666.  
  2667.   A valid  filespec is  parsed and  assigned to  the four  global
  2668.   filespec variables as follows:
  2669.  
  2670.   $drive    Contains the  drive letter  and colon  (A:) or a null
  2671.             string if  the returned  filespec contains  no  drive
  2672.             specification.
  2673.  
  2674.   $subdir   Contains the  subdirectory list  from  the  filespec,
  2675.             including the  trailing backslash.  Contains the null
  2676.             string if the filespec has no subdirectory component.
  2677.  
  2678.   $name     Contains the filename part of the filespec.
  2679.  
  2680.   $ext      Contains  the   extension  part   of  the   filespec,
  2681.             including the  dot.   However, if  the user  enters a
  2682.             filespec that  contains no  extension or  dot, and no
  2683.             default is  supplied, then this variable will contain
  2684.             a null string.
  2685.  
  2686.   Note that  on return  from *parse_filespec, the values of these
  2687.   four variables  are such that their concatenation is guaranteed
  2688.   to be  a valid  filespec.  In fact, $drive$subdir$name$ext will
  2689.   have exactly the same value as the input parameter $filespec.
  2690.  
  2691. Parameter validation
  2692.  
  2693.   *Parse_filespec ensures  that $filespec  is syntactically well-
  2694.   formed.   It ensures  the following: that the drive designator,
  2695.   if any,  is valid  (see the  entry for  *val_drive); that  only
  2696.   valid characters  occur in  the subdirectory  names, file name,
  2697.   and extension  (see .FILECHARS  on page  14);  and  that  these
  2698.   components do  not exceed  the maximum  allowed  lengths  of  8
  2699.   characters for subdirectory and file names and 3 characters for
  2700.   the extension.
  2701.  
  2702.   When $filespec  is not  well-formed, *parse_filespec is able to
  2703.   display a  message describing  exactly what  is wrong  with the
  2704.   filespec.   The #report  parameter  allows  the  programmer  to
  2705.   control whether  or not  these messages  are displayed.   In an
  2706.   interactive routine,  this parameter  would normally  be set to
  2707.   .YES in  order to give the user as much information as possible
  2708.   about why  the filespec  just typed was invalid.  However, in a
  2709.   noninteractive  routine,   such  as   when  a  program-supplied
  2710.   filespec is  being parsed, such messages would be mysterious to
  2711.   the user.  In such cases, #report should be set to .NO, and the
  2712.   program should  be written  to test  the return  value and make
  2713.   some sensible response if the parse fails.
  2714.  
  2715.  
  2716. Example
  2717.  
  2718.   ; Is the name part of $filespec exactly 6 characters
  2719.   ; long?
  2720.   
  2721.   num function *six_char_name($filespec)
  2722.   
  2723.   ; use local copies of filespec variables so as not to
  2724.   ; interfere with global ones
  2725.   
  2726.   declare $drive,$subdir,$name,$ext
  2727.   
  2728.   if (*parse_filespec($filespec,.NO) +
  2729.         and *strlen($name) == 6)
  2730.      return .YES
  2731.   else
  2732.      return .NO
  2733.   end if
  2734.   
  2735.   end function
  2736.  
  2737.  
  2738. _________________________________________________________________
  2739.  
  2740. retry($message,$topic)
  2741. _________________________________________________________________
  2742.  
  2743.  
  2744. Description
  2745.  
  2746.   Rings the  bell and  displays an  error message.   It then adds
  2747.   "Try again  (type ? for help)" if a help topic is available, or
  2748.   simply "Try again" if no help is available.
  2749.  
  2750. Parameters
  2751.  
  2752.   $message  the error message to display
  2753.   $topic    the help  topic for  the question  that was  answered
  2754.             incorrectly
  2755.  
  2756. Return value
  2757.  
  2758.   None.
  2759.  
  2760. Remarks
  2761.  
  2762.   Because *retry  adds "Try  again" to the end of the message, it
  2763.   is suitable  only for  error messages  regarding incorrect user
  2764.   response to  a question.   For more general error messages, use
  2765.   *message.
  2766.  
  2767.   If the  total length  of $message  plus  the  "Try  again"  tag
  2768.   exceeds the  width of  the screen, the "Try again" is displayed
  2769.   on a  new line.   No check is made, however, to see if $message
  2770.   will fit on one screen line.
  2771.  
  2772.   To indent the message, include leading spaces in $message.  The
  2773.   "Try again"  tag will  be indented the same number of spaces if
  2774.   it is displayed on a second line.
  2775.  
  2776. Example
  2777.  
  2778.   ; get unique input and output markers
  2779.   loop
  2780.      $in_marker=*get_code("Input record marker","","",+
  2781.         0,.MAXCODE)
  2782.      $out_marker=*get_code("Output record marker","","",+
  2783.         0,.MAXCODE)
  2784.      exit if ($in_marker <> $out_marker)
  2785.      retry("Record markers must be different","")
  2786.   end loop
  2787.  
  2788.  
  2789. _________________________________________________________________
  2790.  
  2791. *to_lower($string)
  2792. _________________________________________________________________
  2793.  
  2794.  
  2795. Description
  2796.  
  2797.   Converts all upper-case letters in $string to lower case.
  2798.  
  2799. Parameters
  2800.  
  2801.   $string   the string to convert
  2802.  
  2803. Return value
  2804.  
  2805.   A string  which is  a copy  of $string  that has all upper-case
  2806.   letters converted  to lower  case.  Other characters in $string
  2807.   are unchanged.
  2808.  
  2809. Example
  2810.  
  2811.   ; ensure standard format marker is all lower case
  2812.   
  2813.   $marker=*to_lower($marker)
  2814.  
  2815.  
  2816. _________________________________________________________________
  2817.  
  2818. *to_upper($string)
  2819. _________________________________________________________________
  2820.  
  2821.  
  2822. Description
  2823.  
  2824.   Converts all lower-case letters in $string to upper case.
  2825.  
  2826. Parameters
  2827.  
  2828.   $string   the string to convert
  2829.  
  2830. Return value
  2831.  
  2832.   A string  which is  a copy  of $string  that has all lower-case
  2833.   letters converted  to upper  case.  Other characters in $string
  2834.   are unchanged.
  2835.  
  2836. Example
  2837.  
  2838.   ; ensure drive name is upper case
  2839.   
  2840.   $drive=*to_upper($drive)
  2841.  
  2842.  
  2843. _________________________________________________________________
  2844.  
  2845. *trim($string)
  2846. _________________________________________________________________
  2847.  
  2848.  
  2849. Description
  2850.  
  2851.   Removes leading  and trailing blanks (that is, spaces and tabs)
  2852.   from a string.
  2853.  
  2854. Parameters
  2855.  
  2856.   $string   the string to trim
  2857.  
  2858. Return value
  2859.  
  2860.   A string  which is  a copy  of $string  without any  leading or
  2861.   trailing blanks.
  2862.  
  2863. Remarks
  2864.  
  2865.   A string  consisting entirely  of blanks is converted to a null
  2866.   string.
  2867.  
  2868. Example
  2869.  
  2870.   $address=*get_str("Address","","address",0,60)
  2871.   
  2872.   $address=*trim($address)
  2873.  
  2874.  
  2875. _________________________________________________________________
  2876.  
  2877. *val_dir($dir)
  2878. _________________________________________________________________
  2879.  
  2880.  
  2881. Description
  2882.  
  2883.   Validates a directory path as being syntactically well-formed.
  2884.  
  2885. Parameters
  2886.  
  2887.   $dir      partial path (includes only subdirectory names)
  2888.  
  2889. Return value
  2890.  
  2891.   A number which is .YES if the path is well-formed, or .NO if it
  2892.   is invalid.
  2893.  
  2894. Remarks
  2895.  
  2896.   Note that  this subroutine  does not  check to  see if the path
  2897.   actually exists.   It  only  checks  the  syntax  of  the  path
  2898.   expression.
  2899.  
  2900.   Displays  an   error  message  if  the  path  contains  invalid
  2901.   characters.   The path  does not  have to  begin or  end with a
  2902.   backslash.
  2903.  
  2904.   Valid characters  for a  path include  the  backslash  and  all
  2905.   characters which  are valid  in a subdirectory name.  These are
  2906.   the same as the characters valid in a file name (see .FILECHARS
  2907.   on page 14 for a list).
  2908.  
  2909. Example
  2910.  
  2911.   loop
  2912.      $directory=*get_str("Directory for .TMP files","",+
  2913.         "tmp_files",0,65)
  2914.      exit if (*val_dir($directory))
  2915.   end loop
  2916.  
  2917.  
  2918. _________________________________________________________________
  2919.  
  2920. *val_drive($drive)
  2921. _________________________________________________________________
  2922.  
  2923.  
  2924. Description
  2925.  
  2926.   Validates a drive designator as referring to an existing drive.
  2927.  
  2928. Parameters
  2929.  
  2930.   $drive    the drive designator to be tested
  2931.  
  2932. Return value
  2933.  
  2934.   A number  which is  .YES if the drive exists, or .NO if it does
  2935.   not.
  2936.  
  2937. Remarks
  2938.  
  2939.   $Drive may  be a  single letter, or it may be a letter followed
  2940.   by a  colon.  $Drive may also contain the null string, in which
  2941.   case it is a valid designation for the current.
  2942.  
  2943.   On PC-compatibles, this subroutine works as expected, returning
  2944.   .YES for valid drives, and .NO for invalid drives.
  2945.  
  2946.   On the  Sharp PC-5000,  *val_drive is complicated by a quirk of
  2947.   that machine:  the  operating  system  thinks  that  drives  A:
  2948.   through O:  are always  available.  Attempting to access one of
  2949.   the nonexistent  drives (like  E: or  M:)  invokes  the  MS-DOS
  2950.   critical error  handler.   The user will get the "Abort, Retry,
  2951.   Ignore" message,  and will  have to abort, losing any data that
  2952.   was not  yet written  to a  file. *Val_drive  attempts  to  get
  2953.   around this problem in two ways:
  2954.  
  2955.   The first  method requires  no user  intervention.   All  drive
  2956.   requests  are   checked  against   the  list  "ABCDG"  and  are
  2957.   considered invalid  if they  are not  on the  list.  ("P" for a
  2958.   ramdisk is  automatically added  to the  list if  a ramdisk  is
  2959.   installed.)   This method  is not  perfect, since it recognizes
  2960.   all possible  drives for  the Sharp, not just the ones actually
  2961.   installed.
  2962.  
  2963.   The second  method requires  the RAP program to be invoked with
  2964.   the command-line  parameter /drive=, where the = is followed by
  2965.   a list  of actual  drive  letters.    This  is,  unfortunately,
  2966.   specific to  the particular  machine.  For example, if the user
  2967.   has a  dual 5  1/4" drive, and uses a ramdisk, the command-line
  2968.   parameter should be:
  2969.  
  2970.                          rap /drive=ABCDP
  2971.  
  2972.   Regardless of  machine type, the list of valid drive letters is
  2973.   contained in  the global  variable $valdr.   Your  programs may
  2974.   test the value of this variable, but should never change it.
  2975.  
  2976. User error handling
  2977.  
  2978.   An error message is displayed if the drive is invalid.
  2979.  
  2980. Example
  2981.  
  2982.   ; get and validate a drive designator
  2983.   loop
  2984.      $dr=*get_str("What drive will you be using","","",2,2)
  2985.      exit if (*val_drive($dr))
  2986.   end loop
  2987.  
  2988.  
  2989. _________________________________________________________________
  2990.  
  2991. *val_ext($ext)
  2992. _________________________________________________________________
  2993.  
  2994.  
  2995. Description
  2996.  
  2997.   Validates a  file name  extension as  being syntactically  well
  2998.   formed.
  2999.  
  3000. Parameters
  3001.  
  3002.   $ext      the extension to be checked
  3003.  
  3004. Return value
  3005.  
  3006.   A number  which is .YES if the extension is valid, or .NO if it
  3007.   is not.
  3008.  
  3009. Remarks
  3010.  
  3011.   Displays an  error message if extension is invalid.  An invalid
  3012.   extension is  one that  is more  than  three  characters  long,
  3013.   contains  characters  not  allowed  in  filenames,  contains  a
  3014.   backslash or  colon, or  has  a  dot  that  is  not  the  first
  3015.   character.  Note that the null string is a valid extension.
  3016.  
  3017.   Valid characters  for extensions are the same as those for file
  3018.   names.  See .FILECHARS on page 14 for a list.
  3019.  
  3020. Example
  3021.  
  3022.   loop
  3023.      $newext=*get_str("New extension for $name$ext","","",+
  3024.         0,4)
  3025.      $newext=*ensure_dot($newext)
  3026.      exit if (*val_ext($newext))
  3027.   end loop
  3028.   
  3029.   $filespec=$name$newext
  3030.  
  3031.  
  3032. _________________________________________________________________
  3033.  
  3034. *yes($query,$default,$topic)
  3035. _________________________________________________________________
  3036.  
  3037.  
  3038. Description
  3039.  
  3040.   Tests if  the user  answers yes  to  the  query,  supplying  an
  3041.   optional default response.
  3042.  
  3043. Parameters
  3044.  
  3045.   $query    the question to ask
  3046.   $default  the default response ("", if none)
  3047.   $topic    the help topic ("", if none)
  3048.  
  3049. Return value
  3050.  
  3051.   A number  which is .YES if the answer was yes, or .NO if it was
  3052.   no.
  3053.  
  3054. Remarks
  3055.  
  3056.   The user's response must be one of the following: y, yes, n, or
  3057.   no.  Case is ignored, as are leading or trailing blanks.
  3058.  
  3059. User error handling
  3060.  
  3061.   If an  invalid response  is given,  *yes displays  the  message
  3062.   "Please type yes or no" and redisplays the query.
  3063.  
  3064. Parameter validation
  3065.  
  3066.   *Yes does  not validate  $default before  using it.  This means
  3067.   that if  an invalid  $default was passed, it will be displayed,
  3068.   but the  user error handling will reject it if the user presses
  3069.   just Enter.
  3070.  
  3071. Example
  3072.  
  3073.   #verbose=*yes("Do you want instructions","n",+
  3074.      "instructions")
  3075.  
  3076.